AtCoder Beginner Contest 265 Solution更好的阅读体验戳此进入题面链接题面 Luogu 链接abc不说了[ABC265D] Iroha and Haiku (New ABC Edition)题面SolutionCode[ABC265E] Warp题面SolutionCode[ABC265F] Manhattan Cafe题面SolutionCode[ABC265G] 012 Inversion题面SolutionCode题面SolutionCodeUPD
题意:
有一个长度为
判断有满足以下所有条件的整数
一个比较显然的思路就是枚举 set 也行,复杂度都是
xxxxxxxxxx77123
45678910
11using namespace std;12
13mt19937 rnd(random_device{}());14int rndd(int l, int r){return rnd() % (r - l + 1) + l;}15bool rnddd(int x){return rndd(1, 100) <= x;}16
17typedef unsigned int uint;18typedef unsigned long long unll;19typedef long long ll;20typedef long double ld;21
22template < typename T = int >23inline T read(void);24
25int N;26ll P, Q, R;27ll a[210000];28ll sum[210000];29
30int main(){31 N = read(), P = read < ll >(), Q = read < ll >(), R = read < ll >();32 for(int i = 1; i <= N; ++i)sum[i] = sum[i - 1] + (a[i] = read());33 for(int x = 1; x <= N - 2; ++x){34 int l = x, r = N - 2, ans(-1);35 while(l <= r){36 int mid = (l + r) >> 1;37 if(sum[mid] - sum[x - 1] >= P)ans = mid, r = mid - 1;38 else l = mid + 1;39 }if(!~ans || sum[ans] - sum[x - 1] != P)continue;40 int y = ans + 1;41 // printf("x = %d, y = %d\n", x, y);42 l = y, r = N - 1, ans = -1;43 while(l <= r){44 int mid = (l + r) >> 1;45 if(sum[mid] - sum[y - 1] >= Q)ans = mid, r = mid - 1;46 else l = mid + 1;47 }if(!~ans || sum[ans] - sum[y - 1] != Q)continue;48 int z = ans + 1;49 // printf("x = %d, y = %d, z = %d\n", x, y, z);50 l = z, r = N, ans = -1;51 while(l <= r){52 int mid = (l + r) >> 1;53 if(sum[mid] - sum[z - 1] >= R)ans = mid, r = mid - 1;54 else l = mid + 1;55 }if(!~ans || sum[ans] - sum[z - 1] != R)continue;56 // printf("x = %d, y = %d, z = %d, w = %d\n", x, y, z, ans + 1);57 printf("Yes\n"), exit(0);58 }printf("No\n");59 fprintf(stderr, "Time: %.6lf\n", (double)clock() / CLOCKS_PER_SEC);60 return 0;61}62
63template < typename T >64inline T read(void){65 T ret(0);66 int flag(1);67 char c = getchar();68 while(c != '-' && !isdigit(c))c = getchar();69 if(c == '-')flag = -1, c = getchar();70 while(isdigit(c)){71 ret *= 10;72 ret += int(c - '0');73 c = getchar();74 }75 ret *= flag;76 return ret;77}ZK 现在在一个二维平面。他现在会进行
同时在这个平面上有
问
十分显然的 DP,令
xxxxxxxxxx65123
456789
10using namespace std;11
12mt19937 rnd(random_device{}());13int rndd(int l, int r){return rnd() % (r - l + 1) + l;}14bool rnddd(int x){return rndd(1, 100) <= x;}15
16typedef unsigned int uint;17typedef unsigned long long unll;18typedef long long ll;19typedef long double ld;20
2122
23template < typename T = int >24inline T read(void);25
26int N, M;27ll A, B, C, D, E, F;28set < pair < ll, ll > > blk;29ll dp[310][310][310];30ll ans(0);31bool isBlocked(pair < ll, ll > pos){return blk.find({pos.first, pos.second}) != blk.end();}32pair < ll, ll > GetPos(int i, int j, int k){return {A * i + C * j + E * k, B * i + D * j + F * k};}33
34int main(){35 N = read(), M = read();36 A = read(), B = read(), C = read(), D = read(), E = read(), F = read();37 while(M--){int x = read(), y = read(); blk.insert({x, y});}38 dp[0][0][0] = 1;39 for(int i = 0; i <= N; ++i)40 for(int j = 0; j <= N; ++j)41 for(int k = 0; k <= N; ++k){42 if(i + j + k > N || isBlocked(GetPos(i, j, k)))continue;43 (dp[i][j][k] += ((i ? dp[i - 1][j][k] : 0) + (j ? dp[i][j - 1][k] : 0) + (k ? dp[i][j][k - 1] : 0)) % MOD) %= MOD;44 if(i + j + k == N)(ans += dp[i][j][k]) %= MOD;45 }46 printf("%lld\n", ans);47 fprintf(stderr, "Time: %.6lf\n", (double)clock() / CLOCKS_PER_SEC);48 return 0;49}50
51template < typename T >52inline T read(void){53 T ret(0);54 int flag(1);55 char c = getchar();56 while(c != '-' && !isdigit(c))c = getchar();57 if(c == '-')flag = -1, c = getchar();58 while(isdigit(c)){59 ret *= 10;60 ret += int(c - '0');61 c = getchar();62 }63 ret *= flag;64 return ret;65}在
细节巨多的 DP。
首先有一个较为显然的
然后这个东西实际上是可以通过类似前缀和的东西转移的,但是是类似对角线前缀和的,比较复杂细节巨多,所以这里参考以下机房大佬 @sssmzy 的做法。
考虑将状态修改为
这个时候考虑两种可能性,对于某次枚举的位置
考虑对于
具体来说,维护一个
转移的意义即为在
于是每次处理完 DP 后清空并重新维护
最终复杂度为
xxxxxxxxxx81123
45678910
11using namespace std;12
13mt19937 rnd(random_device{}());14int rndd(int l, int r){return rnd() % (r - l + 1) + l;}15bool rnddd(int x){return rndd(1, 100) <= x;}16
17typedef unsigned int uint;18typedef unsigned long long unll;19typedef long long ll;20typedef long double ld;21
2223
24template < typename T = int >25inline T read(void);26
27int N, D;28int P[110], Q[110];29ll dp[2100][1100];30ll sum[2100][1100];31ll sum2[2100][1100];32ll ans(0);33
34int main(){35 N = read(), D = read();36 for(int i = 1; i <= N; ++i)P[i] = read();37 for(int i = 1; i <= N; ++i)Q[i] = read();38 dp[0][0] = 1;39 for(int j = 0; j <= D * 2; ++j)40 for(int k = 0; k <= D; ++k)41 sum[j][k] = ((k - 1 >= 0 ? sum[j][k - 1] : 0) + dp[j][k]) % MOD,42 sum2[j][k] = ((j - 2 >= 0 && k - 1 >= 0 ? sum2[j - 2][k - 1] : 0) + dp[j][k]) % MOD;43 for(int i = 1; i <= N; ++i){44 for(int j = 0; j <= D * 2; ++j)45 for(int k = 0; k <= D; ++k){46 int dis = abs(P[i] - Q[i]);47 dp[j][k] = j >= dis48 ?49 ((sum[j - dis][k] - (k - dis - 1 >= 0 ? sum[j - dis][k - dis - 1] : 0) + MOD) % MOD +50 (j - dis - 2 >= 0 && k - 1 >= 0 ? sum2[j - dis - 2][k - 1] % MOD : 0) +51 (j - dis - 2 >= 0 && k - dis - 1 >= 0 ? sum2[j - dis - 2][k - dis - 1] % MOD : 0)) % MOD52 : 0;53 }54 memset(sum, 0, sizeof sum), memset(sum2, 0, sizeof sum2);55 for(int j = 0; j <= D * 2; ++j)56 for(int k = 0; k <= D; ++k)57 sum[j][k] = ((k - 1 >= 0 ? sum[j][k - 1] : 0) + dp[j][k]) % MOD,58 sum2[j][k] = ((j - 2 >= 0 && k - 1 >= 0 ? sum2[j - 2][k - 1] : 0) + dp[j][k]) % MOD;59 }60 for(int j = 0; j <= D * 2; ++j)for(int k = 0; k <= min(j, D); ++k)61 if(j - k <= D) (ans += dp[j][k]) %= MOD;62 printf("%lld\n", ans);63 fprintf(stderr, "Time: %.6lf\n", (double)clock() / CLOCKS_PER_SEC);64 return 0;65}66
67template < typename T >68inline T read(void){69 T ret(0);70 int flag(1);71 char c = getchar();72 while(c != '-' && !isdigit(c))c = getchar();73 if(c == '-')flag = -1, c = getchar();74 while(isdigit(c)){75 ret *= 10;76 ret += int(c - '0');77 c = getchar();78 }79 ret *= flag;80 return ret;81}有一个元素全为
1 L R:询问区间 2 L R S T U:将区间 显然线段树。每个节点维护
xxxxxxxxxx136123
45678910
11using namespace std;12
13mt19937 rnd(random_device{}());14int rndd(int l, int r){return rnd() % (r - l + 1) + l;}15bool rnddd(int x){return rndd(1, 100) <= x;}16
17typedef unsigned int uint;18typedef unsigned long long unll;19typedef long long ll;20typedef long double ld;21
22template < typename T = int >23inline T read(void);24
25int N, Q;26int A[110000];27struct RetNode{28 ll cnt;29 ll siz0, siz1, siz2;30};31
32class SegTree{33private:34 ll cnt[110000 << 2][3][3], siz[110000 << 2][3];35 ll lz[110000 << 2][3];36 37 38 39public:40 SegTree(void){for(int i = 0; i <= 101000 << 2; ++i)for(int j = 0; j <= 2; ++j)lz[i][j] = j;}41 void Pushup(int p){42 for(int i = 0; i <= 2; ++i)siz[p][i] = siz[LS][i] + siz[RS][i];43 for(int i = 0; i <= 2; ++i)for(int j = 0; j <= 2; ++j)44 cnt[p][i][j] = cnt[LS][i][j] + cnt[RS][i][j] + siz[LS][i] * siz[RS][j];45 }46 void Pushdown(int p){47 if(lz[p][0] == 0 && lz[p][1] == 1 && lz[p][2] == 2)return;48 for(int i = 0; i <= 2; ++i)lz[LS][i] = lz[p][lz[LS][i]];49 for(int i = 0; i <= 2; ++i)lz[RS][i] = lz[p][lz[RS][i]];50 ll tsiz[3]; memset(tsiz, 0, sizeof tsiz);51 ll tcnt[3][3]; memset(tcnt, 0, sizeof tcnt);52 for(int i = 0; i <= 2; ++i)tsiz[lz[p][i]] += siz[LS][i];53 for(int i = 0; i <= 2; ++i)for(int j = 0; j <= 2; ++j)54 tcnt[lz[p][i]][lz[p][j]] += cnt[LS][i][j];55 for(int i = 0; i <= 2; ++i)siz[LS][i] = tsiz[i];56 for(int i = 0; i <= 2; ++i)for(int j = 0; j <= 2; ++j)cnt[LS][i][j] = tcnt[i][j];57 memset(tsiz, 0, sizeof tsiz), memset(tcnt, 0, sizeof tcnt);58 for(int i = 0; i <= 2; ++i)tsiz[lz[p][i]] += siz[RS][i];59 for(int i = 0; i <= 2; ++i)for(int j = 0; j <= 2; ++j)60 tcnt[lz[p][i]][lz[p][j]] += cnt[RS][i][j];61 for(int i = 0; i <= 2; ++i)siz[RS][i] = tsiz[i];62 for(int i = 0; i <= 2; ++i)for(int j = 0; j <= 2; ++j)cnt[RS][i][j] = tcnt[i][j];63 for(int i = 0; i <= 2; ++i)lz[p][i] = i;64 }65 void Build(int p = 1, int gl = 1, int gr = N){66 if(gl == gr)return siz[p][A[gl = gr]] = 1, void();67 Build(LS, gl, MID), Build(RS, MID + 1, gr);68 Pushup(p);69 }70 RetNode Query(int l, int r, int p = 1, int gl = 1, int gr = N){71 if(l <= gl && gr <= r)72 return RetNode{cnt[p][2][0] + cnt[p][2][1] + cnt[p][1][0], siz[p][0], siz[p][1], siz[p][2]};73 if(gr < l || r < gl)return RetNode{0, 0, 0, 0};74 Pushdown(p);75 auto Lret = Query(l, r, LS, gl, MID), Rret = Query(l, r, RS, MID + 1, gr);76 return RetNode{77 Lret.cnt + Rret.cnt + Lret.siz2 * Rret.siz0 + Lret.siz2 * Rret.siz1 + Lret.siz1 * Rret.siz0,78 Lret.siz0 + Rret.siz0,79 Lret.siz1 + Rret.siz1,80 Lret.siz2 + Rret.siz281 };82 }83 void Modify(int l, int r, int S, int T, int U, int p = 1, int gl = 1, int gr = N){84 if(l <= gl && gr <= r){85 ll tsiz[3]; memset(tsiz, 0, sizeof tsiz);86 ll tcnt[3][3]; memset(tcnt, 0, sizeof tcnt);87 int ctlz[3] = {S, T, U};88 for(int i = 0; i <= 2; ++i)lz[p][i] = ctlz[lz[p][i]];89 for(int i = 0; i <= 2; ++i)tsiz[ctlz[i]] += siz[p][i];90 for(int i = 0; i <= 2; ++i)for(int j = 0; j <= 2; ++j)91 tcnt[ctlz[i]][ctlz[j]] += cnt[p][i][j];92 for(int i = 0; i <= 2; ++i)siz[p][i] = tsiz[i];93 for(int i = 0; i <= 2; ++i)for(int j = 0; j <= 2; ++j)cnt[p][i][j] = tcnt[i][j];94 return;95 }Pushdown(p);96 if(l <= MID)Modify(l, r, S, T, U, LS, gl, MID);97 if(MID + 1 <= r)Modify(l, r, S, T, U, RS, MID + 1, gr);98 Pushup(p);99 }100}st;101
102int main(){103 // freopen("in.txt", "r", stdin);104 // freopen("out.txt", "w", stdout);105 N = read(), Q = read();106 for(int i = 1; i <= N; ++i)A[i] = read();107 st.Build();108 while(Q--){109 int opt = read();110 if(opt == 1){111 int l = read(), r = read();112 printf("%lld\n", st.Query(l, r).cnt);113 }else{114 int l = read(), r = read(), S = read(), T = read(), U = read();115 st.Modify(l, r, S, T, U);116 }117 }118 fprintf(stderr, "Time: %.6lf\n", (double)clock() / CLOCKS_PER_SEC);119 return 0;120}121
122template < typename T >123inline T read(void){124 T ret(0);125 int flag(1);126 char c = getchar();127 while(c != '-' && !isdigit(c))c = getchar();128 if(c == '-')flag = -1, c = getchar();129 while(isdigit(c)){130 ret *= 10;131 ret += int(c - '0');132 c = getchar();133 }134 ret *= flag;135 return ret;136}
xxxxxxxxxx11
update-2022__ 初稿