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
也行,复杂度都是
xxxxxxxxxx
771
2
3
4
5
6
7
8
9
10
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,令
xxxxxxxxxx
651
2
3
4
5
6
7
8
9
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
21
22
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 后清空并重新维护
最终复杂度为
xxxxxxxxxx
811
2
3
4
5
6
7
8
9
10
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
22
23
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 >= dis
48 ?
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)) % MOD
52 : 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
:将区间 显然线段树。每个节点维护
xxxxxxxxxx
1361
2
3
4
5
6
7
8
9
10
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.siz2
81 };
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}
xxxxxxxxxx
11
update-2022__ 初稿