AtCoder Beginner Contest 322
B - Prefix and Suffix
难度: ⭐
题目大意
给定两个字符串t和s, 如果t是s的前缀则输出1, 如果是后缀则输出2, 如果都是则输出0, 都不是则输出3;
解题思路
暴力即可;
神秘代码
#include<bits/stdc++.h>
#define int l1ng l1ng
#define IOS ios::sync_with_stdio(false), cin.tie(0),cout.tie(0)
#define endl '\n'
using namespace std;
const int N = 2e5 + 10, mod = 998244353;
typedef pair<int, int> PII;
int n, m, idx;
signed main() {
string s,t;
cin>>n>>m>>s>>t;
string pr=t.substr(0,n);
string su=t.substr(m-n,n);
if(pr==s&&su==s) cout<<0;
else if(pr==s) cout<<1;
else if(su==s) cout<<2;
else cout<<3;
return 0;
}
C - Festival
难度: ⭐
题目大意
一个城市计划在n天中的m天放烟花, 并且给出这m天; 对于这n天中的每一天, 输出其距离未来最近的放烟花的一天还有几天;
解题思路
双指针暴力即可;
神秘代码
#include<bits/stdc++.h>
#define int l1ng l1ng
#define IOS ios::sync_with_stdio(false), cin.tie(0),cout.tie(0)
#define endl '\n'
using namespace std;
const int N = 2e5 + 10, mod = 998244353;
typedef pair<int, int> PII;
int n, m, idx;
int f[N];
signed main() {
cin>>n>>m;
for(int i=1;i<=n;i++) cin>>f[i];
idx=1;
for(int i=1;i<=n;i++){
while(i>f[idx]) idx++;
cout<<f[idx]-i<<endl;
}
return 0;
}
D - Polyomino
难度: ⭐⭐⭐
题目大意
给定三个几何图形, 保证这三个几何图形的大小不会超出一个4*4的方格, 请问能否用这三个图形拼出一个4 * 4的正方形;
解题思路
一道很复杂的暴力模拟, 这天实在是没心思看了, 等以后再补吧...未来可期题解
神秘代码
E - Pr1duct Devel1pment
难度: ⭐⭐⭐
题目大意
一个项目需要k个物品都至少到达p个数量; 现在有n个套餐, 每个套餐都可以给这k个物品加若干个数量, 每个套餐都要各自的价格; 请问在满足项目要求的情况下需要的最小花费是多少;
解题思路
一个很明显的dp, 并且我们发现k和p的数据范围最大是5, 那我们可以直接开一个6维数组, 并且用前i个套餐满足各个属性达到各个值所需要的最小花费; 一开始我还在想因为不确定k所以不知道数组开几维, 后来一想不用考虑这个, 对于多出来的维度我们把他们的要求设为0就可以了, 并且用滚动数组可以把第1维也省掉, 所以开5维数组就够了; 因为用滚动数组, 所以我们遍历状态时要倒序遍历, 并且我们要求是大于等于p, 所以状态转移时小于0的状态也是可以的, 我们可以把这些都归到0的状态上即可;
神秘代码
#include<bits/stdc++.h>
#define int l1ng l1ng
#define IOS ios::sync_with_stdio(false), cin.tie(0),cout.tie(0)
#define endl '\n'
using namespace std;
const int N = 2e5 + 10, mod = 998244353;
typedef pair<int, int> PII;
int n, m, idx;
int f[N], p[110][10];
int dp[6][6][6][6][6];
signed main() {
int k;
cin >> n >> m >> k;
for (int i = 1; i <= n; i++) {
cin >> f[i];
for (int j = 1; j <= m; j++) {
cin >> p[i][j];
}
}
for (int h1 = 0; h1 <= k; h1++) {
for (int h2 = 0; h2 <= k; h2++) {
for (int h3 = 0; h3 <= k; h3++) {
for (int h4 = 0; h4 <= k; h4++) {
for (int h5 = 0; h5 <= k; h5++) {
dp[h1][h2][h3][h4][h5] = 1e12 + 10;
}
}
}
}
}
dp[0][0][0][0][0] = 0;
for (int i = 1; i <= n; i++) {
for (int h1 = k; h1 >= 0; h1--) {
for (int h2 = k; h2 >= 0; h2--) {
for (int h3 = k; h3 >= 0; h3--) {
for (int h4 = k; h4 >= 0; h4--) {
for (int h5 = k; h5 >= 0; h5--) {
int x1 = max(h1 - p[i][1], 0ll);
int x2 = max(h2 - p[i][2], 0ll);
int x3 = max(h3 - p[i][3], 0ll);
int x4 = max(h4 - p[i][4], 0ll);
int x5 = max(h5 - p[i][5], 0ll);
dp[h1][h2][h3][h4][h5] = min(dp[h1][h2][h3][h4][h5], dp[x1][x2][x3][x4][x5] + f[i]);
}
}
}
}
}
}
int d[6];
for (int i = 1; i <= 5; i++) {
if (i <= m) d[i] = k;
else d[i] = 0;
}
int res = dp[d[1]][d[2]][d[3]][d[4]][d[5]];
if (res == 1e12 + 10) res = -1;
cout << res;
return 0;
}
F - Vacation Query
难度: ⭐⭐⭐⭐
题目大意
给定一个由0/1组成的数列, 我们可以对其进行n次操作, 操作分为两种, 每种都给出一个区间, 一是输出这个区间中连续的1的最长长度; 二是将这个区间里的1变成0, 0变成1;
解题思路
很明显的一个线段树, 我们需要维护8个值: 区间边界: l, r; 翻转标记: t, 区间长度: k; 区间中最长连续1/0的长度: m1, m0; 区间前缀/后缀连续1的长度: l1, r1; 区间前缀/后缀连续0的长度: l0, r0; 需要维护前缀和后缀是因为方便合并区间时计算最长的连续1的长度;
build函数就不多说了, 正常写就行;
pushup函数中考虑区间合并, m1, m0, l1, r1, l0, r0都可能改变, 所以需要一个一个更新; 对于前缀连续1的长度L1, 如果左区间的l1的长度等于区间长度(也就是整个区间都是1), 那么L1就可以更新为左区间的长度加上右区间的l1; 否则的话就直接把L1赋值为左区间的l1即可; 其他的前缀和后缀都同理; 对于M1来说, 他有三种可能, 一是左区间的m1, 二是右区间的m1, 三是左区间的后缀1和右区间的前缀1所组成的新的连续的1; 三者取最大值即可, m0同理;
pushdown函数主要作用是区间翻转, 如果根区间的t=1说明左右区间都需要翻转, 首先把左右区间各自的翻转标记k取反, 然后把m1和m0, l1和l0, r1和r0都交换即可;
modify函数的作用也是区间翻转, 不同于之前线段树区间求和的板子, 本题需要找到具体的区间才能对其进行修改, 所以此处的写法不同于模板;
query函数变化最大, 不同于模板, 这里如果函数的返回值只返回一个数无法去求区间的连续1的最长长度, 所以我们让query函数的返回值设为结构体类型; 和modify函数一样我们需要找到准确的区间, 所以当给定区间横跨左右区间时我们需要构建一个新的节点, 这个节点的区间范围和给定的范围一致, 节点各项值的设置和pushdown函数一致;最后输出这个节点的m1即可;
神秘代码
#include<bits/stdc++.h>
#define int long long
#define IOS ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
#define endl '\n'
using namespace std;
const int N = 5e5 + 10, mod = 998244353, inf = 1e18;
typedef pair<int, int> PII;
int n, m, k;
string s;
int res = 0;
struct node{
int l, r;
int fir1, las1;
int fir0, las0;
int max1, max0;
bool rev;
}tr[4 * N];
void Swap(int u){
swap(tr[u].fir1, tr[u].fir0);
swap(tr[u].las1, tr[u].las0);
swap(tr[u].max1, tr[u].max0);
}
void pushup(int u){
auto &root = tr[u], &left = tr[u << 1], &right = tr[u << 1 | 1];
int x = max(left.max1, right.max1);
root.max1 = max(x, left.las1 + right.fir1);
if(left.max0) root.fir1 = left.fir1;
else root.fir1 = left.fir1 + right.fir1;
if(right.max0) root.las1 = right.las1;
else root.las1 = left.las1 + right.las1;
int y = max(left.max0, right.max0);
root.max0 = max(y, left.las0 + right.fir0);
if(left.max1) root.fir0 = left.fir0;
else root.fir0 = left.fir0 + right.fir0;
if(right.max1) root.las0 = right.las0;
else root.las0 = left.las0 + right.las0;
}
void pushdown(int u){
auto &root = tr[u], &left = tr[u << 1], &right = tr[u << 1 | 1];
if(root.rev){
left.rev = !left.rev;
right.rev = !right.rev;
Swap(u << 1);
Swap(u << 1 | 1);
root.rev = false;
}
}
void build(int u, int l, int r){
if(l == r){
if(s[l] == '1') tr[u] = {l, r, 1, 1, 0, 0, 1, 0, false};
else tr[u] = {l, r, 0, 0, 1, 1, 0, 1, false};
}
else{
tr[u] = {l, r};
tr[u].rev = false;
int mid = l + r >> 1;
build(u << 1, l, mid);
build(u << 1 | 1, mid + 1, r);
pushup(u);
}
}
void modify(int u, int l, int r){
if(l <= tr[u].l && r >= tr[u].r){
tr[u].rev = !tr[u].rev;
Swap(u);
}
else{
pushdown(u);
int mid = tr[u].l + tr[u].r >> 1;
if(l <= mid) modify(u << 1, l, r);
if(r > mid) modify(u << 1 | 1, l, r);
pushup(u);
}
}
node query(int u, int l, int r){
if(l <= tr[u].l && r >= tr[u].r){
return tr[u];
}
else{
pushdown(u);
int mid = tr[u].l + tr[u].r >> 1;
bool f1 =false, f2 =false;
node a, b;
if(l <= mid) {
f1 = true;
a = query(u << 1, l, r);
}
if(r > mid) {
f2 = true;
b = query(u << 1 | 1, l, r);
}
if(f1 && f2){
node c;
c = {a.l, b.r};
c.max1 = max(max(a.max1, b.max1), a.las1 + b.fir1);
if(a.max0 == 0) c.fir1 = a.fir1 + b.fir1;
else c.fir1 = a.fir1;
if(b.max0 == 0) c.las1 = b.las1 + a.las1;
else c.las1 = b.las1;
return c;
}
else if(f1) return a;
else if(f2) return b;
}
}
signed main(){
cin >> n >> m;
cin >> s;
s = ' ' + s;
build(1, 1, n);
while(m--){
int a, b, c;
cin >> a >> b >> c;
if(a == 1){
modify(1, b, c);
}
else {
node res = query(1, b, c);
cout << res.max1 << endl;
}
}
return 0;
}