LG-P8280 「MCOI-08」Photoelectric Effect。
有一棵
请问有多少个方案对所有点染色,使得当点对
答案对
一个较为显然的 树形DP + 状压DP,复杂度卡的比较满,细节巨多,但是思路较为显然,赛时写了 !head[p]->nxt
把根也当成叶子了,也就是如果根只有一个子树那就会寄掉。
然后还有个问题就是 Luogu 上必须把边数开到
当然这里的代码是赛时不太正确的,AC Code 参考下文。
xxxxxxxxxx
1521
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
24
25template < typename T = int >
26inline T read(void);
27
28struct Edge{
29 Edge* nxt;
30 int to;
31 OPNEW;
32}ed[210000];
33ROPNEW;
34Edge* head[210000];
35
36int N, K;
37int Smx;
38int opt[10][10];
39struct Node{int S; int col;};
40basic_string < Node > legal[40];
41ll dp[110000][40][6];
42ll merg[40][6];
43
44void Clear(void){
45 for(int i = 0; i <= Smx; ++i)legal[i].clear();
46 for(int i = 0; i <= N; ++i)head[i] = npt;
47 for(int i = 0; i <= N; ++i)for(int S = 0; S <= Smx; ++S)for(int k = 1; k <= K; ++k)dp[i][S][k] = 0;
48}
49void TreeDP(int p = 1, int fa = 0){
50 for(auto i = head[p]; i; i = i->nxt)if(SON != fa)TreeDP(SON, p);
51 if(!head[p]->nxt){for(int i = 0; i < K; ++i)dp[p][1 << i][i + 1] = 1; return;}
52 memset(merg, 0, sizeof merg);
53 bool isbeg(true);
54 for(auto i = head[p]; i; i = i->nxt){
55 if(SON == fa)continue;
56 if(isbeg){
57 isbeg = false;
58 for(int S = 1; S <= Smx; ++S)for(int j = 1; j <= K; ++j)for(int k = 1; k <= K; ++k)(merg[S][j] += dp[SON][S][k]) %= MOD;
59 // printf("p is %d, after merge, merge is : \n", p);
60 // for(int S = 1; S <= Smx; ++S)for(int i = 1; i <= K; ++i)
61 // cout << "merg[" << i << "][" << bitset < 5 >(S) << "] = " << merg[S][i] << endl;
62 continue;
63 }
64 ll lst[40][6];
65 for(int S = 0; S <= Smx; ++S)for(int j = 1; j <= K; ++j)lst[S][j] = merg[S][j], merg[S][j] = 0;
66 ll sum[40]; memset(sum, 0, sizeof sum);
67 for(int S = 1; S <= Smx; ++S)for(int j = 1; j <= K; ++j)(sum[S] += dp[SON][S][j]) %= MOD;
68 for(int S1 = 1; S1 <= Smx; ++S1)
69 for(auto S2 : legal[S1])
70 (merg[S1 | S2.S][S2.col] += lst[S1][S2.col] * sum[S2.S] % MOD) %= MOD;
71 // printf("p is %d, after merge, merge is : \n", p);
72 // for(int S = 1; S <= Smx; ++S)for(int i = 1; i <= K; ++i)
73 // cout << "merg[" << i << "][" << bitset < 5 >(S) << "] = " << merg[S][i] << endl;
74 }
75 for(int S = 1; S <= Smx; ++S)
76 for(int i = 1; i <= K; ++i)
77 (dp[p][S | (1 << (i - 1))][i] += merg[S][i]) %= MOD;
78}
79
80int main(){
81 freopen("color.in", "r", stdin);
82 freopen("color.out", "w", stdout);
83 int T = read();
84 while(T--){
85 Clear();
86 N = read(), K = read();
87 Smx = (1 << K) - 1;
88 for(int i = 1; i <= K; ++i)for(int j = 1; j <= K; ++j)opt[i][j] = read();
89 for(int i = 2; i <= N; ++i){
90 int s = i, t = read();
91 head[s] = new Edge{head[s], t};
92 head[t] = new Edge{head[t], s};
93 }
94 for(int S1 = Smx; S1; S1 = (S1 - 1) & Smx)
95 for(int S2 = Smx; S2; S2 = (S2 - 1) & Smx){
96 int cur(-1);
97 bool flag(true);
98 for(int i = 1; i <= K; ++i){
99 if(!flag)break;
100 for(int j = 1; j <= K; ++j){
101 if(!flag)break;
102 if(S(S1, i) && S(S2, j)){
103 if(opt[i][j] != opt[j][i]){flag = false; break;}
104 if(!~cur)cur = opt[i][j];
105 else if(opt[i][j] != cur)flag = false;
106 }
107 }
108 }if(flag)legal[S1] += Node{S2, cur};
109 }
110 // for(int S = 1; S <= Smx; ++S)for(auto S2 : legal[S]){
111 // cout << bitset < 5 >(S) << "with" << bitset < 5 >(S2.S) << " col is" << S2.col << endl;
112 // }
113 TreeDP();
114 // for(int i = 1; i <= N; ++i)for(int S = 1; S <= Smx; ++S)for(int j = 1; j <= K; ++j)
115 // cout << "dp[" << i << "][" << j << "][" << bitset < 5 >(S) << "] = " << dp[i][S][j] << endl;
116 ll ans(0);
117 for(int S = 1; S <= Smx; ++S)for(int i = 1; i <= K; ++i)(ans += dp[1][S][i]) %= MOD;
118 printf("%lld\n", ans);
119 }
120 fprintf(stderr, "Time: %.6lf\n", (double)clock() / CLOCKS_PER_SEC);
121 return 0;
122}
123
124template < typename T >
125inline T read(void){
126 T ret(0);
127 int flag(1);
128 char c = getchar();
129 while(c != '-' && !isdigit(c))c = getchar();
130 if(c == '-')flag = -1, c = getchar();
131 while(isdigit(c)){
132 ret *= 10;
133 ret += int(c - '0');
134 c = getchar();
135 }
136 ret *= flag;
137 return ret;
138}
139
140/*
141
1422
1435 2
1441 2
1452 1
1461 2 1 4
1475 2
1481 2
1491 1
1501 2 1 4
151
152*/
给定 -1
。
写了篇题解,内容就放在下文了,错的点是没有考虑到应该维护前
xxxxxxxxxx
1931
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
27struct Edge{
28 Edge* nxt;
29 int to;
30 OPNEW;
31}ed[210000];
32ROPNEW;
33Edge* head[110000];
34
35int N, Q;
36ll w[110000];
37int dep[110000], dfn[110000], hson[110000], siz[110000], ffa[110000], tp[110000], idx[110000];
38
39void dfs_pre(int p = 1, int fa = 0){
40 dep[p] = dep[fa] + 1;
41 siz[p] = 1;
42 ffa[p] = fa;
43 for(auto i = head[p]; i; i = i->nxt){
44 if(SON == fa)continue;
45 dfs_pre(SON, p);
46 siz[p] += siz[SON];
47 if(siz[hson[p]] < siz[SON])hson[p] = SON;
48 }
49}
50void dfs_make(int p = 1, int top = 1){
51 tp[p] = top;
52 static int cdfn(0);
53 dfn[p] = ++cdfn;
54 idx[cdfn] = p;
55 if(hson[p])dfs_make(hson[p], top);
56 for(auto i = head[p]; i; i = i->nxt)
57 if(SON != ffa[p] && SON != hson[p])
58 dfs_make(SON, SON);
59}
60
61struct Node{
62 ll v[5], vu[5]; //v_max_with_2, v_unique
63 Node(void){memset(v, 0, sizeof v), memset(vu, 0, sizeof vu);}
64 friend Node operator + (const Node &a, const Node &b){
65 Node ret;
66 basic_string < ll > values;
67 for(int i = 1; i <= 4; ++i){
68 if(a.v[i])values += a.v[i];
69 if(b.v[i])values += b.v[i];
70 }sort(values.begin(), values.end(), greater < ll >());
71 for(auto it = values.begin(); it != values.end() && next(it) != values.end() && next(it, 2) != values.end();)
72 if(*it == *next(it) && *next(it) == *next(it, 2))it = values.erase(it);
73 else advance(it, 1);
74 for(int i = 1; i <= 4; ++i)
75 ret.v[i] = (int)values.size() >= i ? values.at(i - 1) : 0;
76 values.clear();
77 for(int i = 1; i <= 4; ++i){
78 if(a.vu[i])values += a.vu[i];
79 if(b.vu[i])values += b.vu[i];
80 }sort(values.begin(), values.end(), greater < ll >());
81 values.erase(unique(values.begin(), values.end()), values.end());
82 for(int i = 1; i <= 4; ++i)
83 ret.vu[i] = (int)values.size() >= i ? values.at(i - 1) : 0;
84 return ret;
85 }
86};
87
88class SegTree{
89private:
90 Node mx[110000 << 2];
91
92
93
94public:
95 void Pushup(int p){
96 mx[p] = mx[LS] + mx[RS];
97 }
98 void Build(int p = 1, int gl = 1, int gr = N){
99 if(gl == gr)return mx[p].v[1] = mx[p].vu[1] = w[idx[gl = gr]], void();
100 Build(LS, gl, MID), Build(RS, MID + 1, gr);
101 Pushup(p);
102 }
103 void Modify(int id, int v, int p = 1, int gl = 1, int gr = N){//modify dfn////////////////////////////////
104 if(gl == gr)return mx[p].v[1] += v, mx[p].vu[1] += v, void();
105 if(id <= MID)Modify(id, v, LS, gl, MID);
106 else Modify(id, v, RS, MID + 1, gr);
107 Pushup(p);
108 }
109 Node Query(int l, int r, int p = 1, int gl = 1, int gr = N){
110 // printf("Querying l = %d, r = %d\n", l, r);
111 if(l <= gl && gr <= r)return mx[p];
112 if(gr < l || r < gl)return Node();
113 return Query(l, r, LS, gl, MID) + Query(l, r, RS, MID + 1, gr);
114 }
115}st;
116
117void Make(int s, int t){
118 Node cur;
119 while(tp[s] != tp[t]){
120 if(dep[tp[s]] < dep[tp[t]])swap(s, t);
121 cur = cur + st.Query(dfn[tp[s]], dfn[s]);
122 s = ffa[tp[s]];
123 }if(dep[s] < dep[t])swap(s, t);
124 cur = cur + st.Query(dfn[t], dfn[s]);
125 if(!cur.vu[1] || !cur.vu[2]){printf("-1\n"); return;}
126 Node ret = st.Query(1, N);
127 basic_string < ll > tmp;
128 for(int i = 1; i <= 4; ++i)if(ret.v[i])tmp += ret.v[i];
129 for(int i = 1; i <= 2; ++i)
130 if(find(tmp.begin(), tmp.end(), cur.vu[i]) != tmp.end())
131 tmp.erase(find(tmp.begin(), tmp.end(), cur.vu[i]));
132 if((int)tmp.size() < 2 || ((int)tmp.size() == 2 && tmp.at(0) == tmp.at(1))){printf("-1\n"); return;}
133 printf("%lld %lld\n", cur.vu[2], tmp.at(0) == tmp.at(1) ? tmp.at(2) : tmp.at(1));
134 // for(int i = 1; i <= 4; ++i)printf("mxchain mxvu[%d] = %lld\n", i, cur.vu[i]);
135 // for(int i = 1; i <= 4; ++i)printf("mxtree mxv[%d] = %lld\n", i, ret.v[i]);
136}
137
138int main(){
139 freopen("game.in", "r", stdin);
140 freopen("game.out", "w", stdout);
141 N = read();
142 for(int i = 1; i <= N - 1; ++i){
143 int s = read(), t = read();
144 head[s] = new Edge{head[s], t};
145 head[t] = new Edge{head[t], s};
146 }dfs_pre(), dfs_make();
147 for(int i = 1; i <= N; ++i)w[i] = read();
148 st.Build();
149 Q = read();
150 while(Q--){
151 int opt = read(), x = read(), y = read();
152 if(opt == 0)st.Modify(dfn[x], y);
153 else Make(x, y);
154 }
155 fprintf(stderr, "Time: %.6lf\n", (double)clock() / CLOCKS_PER_SEC);
156 return 0;
157}
158
159template < typename T >
160inline T read(void){
161 T ret(0);
162 int flag(1);
163 char c = getchar();
164 while(c != '-' && !isdigit(c))c = getchar();
165 if(c == '-')flag = -1, c = getchar();
166 while(isdigit(c)){
167 ret *= 10;
168 ret += int(c - '0');
169 c = getchar();
170 }
171 ret *= flag;
172 return ret;
173}
174
175/*
176
1777
1781 2
1792 3
1802 4
1811 5
1825 6
1835 7
1845 4 3 2 1 4 3
1856
1861 3 4
1871 2 5
1881 2 1
1890 2 1
1901 2 5
1911 2 1
192
193*/
给定一个
请求出所有合法的子区间数量。多组数据,
不会,跳!
给定
赛时没想出来,确实是一道人类智慧性质题,很有 AGC 的感觉,赛时糊的暴力也挂了。
xxxxxxxxxx
791
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
27struct Range{int l, r;};
28Range R[11];
29int N, Q;
30
31int main(){
32 freopen("segment.in", "r", stdin);
33 freopen("segment.out", "w", stdout);
34 N = read(), Q = read();
35 for(int i = 1; i <= N; ++i)R[i].l = read(), R[i].r = read();
36 sort(R + 1, R + N + 1, [](const Range &a, const Range &b)->bool{return a.l < b.l;});
37 int Smx = (1 << N) - 1;
38 while(Q--){
39 int l = read(), r = read();
40 ll F(0), G(0);
41 for(int S = Smx; S; S = (S - 1) & Smx){
42 int curl(-1), curr(-1);
43 bool flag(true);
44 for(int i = 0; i < N; ++i){
45 if(S & (1 << i)){
46 if(!~curl)curl = R[i + 1].l;
47 if(!~curr)curr = R[i + 1].r;
48 else{
49 if(R[i + 1].l > curr)flag = false;
50 else curr = R[i + 1].r;
51 }
52 }
53 }
54 if(flag && curl == l && curr == r){
55 if(__builtin_popcount(S) & 1)++G;
56 else ++F;
57 }
58 }
59 printf("%lld\n", ((F - G) % MOD + MOD) % MOD);
60 }
61 fprintf(stderr, "Time: %.6lf\n", (double)clock() / CLOCKS_PER_SEC);
62 return 0;
63}
64
65template < typename T >
66inline T read(void){
67 T ret(0);
68 int flag(1);
69 char c = getchar();
70 while(c != '-' && !isdigit(c))c = getchar();
71 if(c == '-')flag = -1, c = getchar();
72 while(isdigit(c)){
73 ret *= 10;
74 ret += int(c - '0');
75 c = getchar();
76 }
77 ret *= flag;
78 return ret;
79}
上文说的差不多了。
xxxxxxxxxx
1581
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
24
25template < typename T = int >
26inline T read(void);
27
28struct Edge{
29 Edge* nxt;
30 int to;
31 OPNEW;
32}ed[2100000];
33ROPNEW;
34Edge* head[110000];
35
36int N, K;
37int Smx;
38int opt[10][10];
39struct Node{int S; int col;};
40basic_string < Node > legal[40];
41ll dp[110000][40][6];
42ll merg[40][6];
43
44void Clear(void){
45 for(int i = 0; i <= Smx; ++i)legal[i].clear();
46 for(int i = 0; i <= N; ++i)head[i] = npt;
47 for(int i = 0; i <= N; ++i)for(int S = 0; S <= Smx; ++S)for(int k = 1; k <= K; ++k)dp[i][S][k] = 0;
48}
49void TreeDP(int p = 1, int fa = 0){
50 for(auto i = head[p]; i; i = i->nxt)if(SON != fa)TreeDP(SON, p);
51 if(p != 1 && !head[p]->nxt){for(int i = 0; i < K; ++i)dp[p][1 << i][i + 1] = 1; return;}
52 memset(merg, 0, sizeof merg);
53 bool isbeg(true);
54 for(auto i = head[p]; i; i = i->nxt){
55 if(SON == fa)continue;
56 if(isbeg){
57 isbeg = false;
58 for(int S = 1; S <= Smx; ++S)for(int j = 1; j <= K; ++j)for(int k = 1; k <= K; ++k)(merg[S][j] += dp[SON][S][k]) %= MOD;
59 // printf("p is %d, after merge, merge is : \n", p);
60 // for(int S = 1; S <= Smx; ++S)for(int i = 1; i <= K; ++i)
61 // cout << "merg[" << i << "][" << bitset < 5 >(S) << "] = " << merg[S][i] << endl;
62 continue;
63 }
64 ll lst[40][6];
65 for(int S = 0; S <= Smx; ++S)for(int j = 1; j <= K; ++j)lst[S][j] = merg[S][j], merg[S][j] = 0;
66 ll sum[40]; memset(sum, 0, sizeof sum);
67 for(int S = 1; S <= Smx; ++S)for(int j = 1; j <= K; ++j)(sum[S] += dp[SON][S][j]) %= MOD;
68 for(int S1 = 1; S1 <= Smx; ++S1)
69 for(auto S2 : legal[S1])
70 (merg[S1 | S2.S][S2.col] += lst[S1][S2.col] * sum[S2.S] % MOD) %= MOD;
71 // printf("p is %d, after merge, merge is : \n", p);
72 // for(int S = 1; S <= Smx; ++S)for(int i = 1; i <= K; ++i)
73 // cout << "merg[" << i << "][" << bitset < 5 >(S) << "] = " << merg[S][i] << endl;
74 }
75 for(int S = 1; S <= Smx; ++S)
76 for(int i = 1; i <= K; ++i)
77 (dp[p][S | (1 << (i - 1))][i] += merg[S][i]) %= MOD;
78 // printf("p = %d\n", p);
79 // for(int S = 1; S <= Smx; ++S)
80 // for(int i = 1; i <= K; ++i){
81
82 // printf("dp[%d][", i); cout << bitset < 5 >(S); printf("] = %lld\n", dp[p][S][i]);
83 // }
84}
85
86int main(){
87 // freopen("color.in", "r", stdin);
88 // freopen("color.out", "w", stdout);
89 int T = read();
90 while(T--){
91 Clear();
92 N = read(), K = read();
93 Smx = (1 << K) - 1;
94 for(int i = 1; i <= K; ++i)for(int j = 1; j <= K; ++j)opt[i][j] = read();
95 for(int i = 2; i <= N; ++i){
96 int s = i, t = read();
97 head[s] = new Edge{head[s], t};
98 head[t] = new Edge{head[t], s};
99 }
100 for(int S1 = Smx; S1; S1 = (S1 - 1) & Smx)
101 for(int S2 = Smx; S2; S2 = (S2 - 1) & Smx){
102 int cur(-1);
103 bool flag(true);
104 for(int i = 1; i <= K; ++i){
105 if(!flag)break;
106 for(int j = 1; j <= K; ++j){
107 if(!flag)break;
108 if(S(S1, i) && S(S2, j)){
109 if(opt[i][j] != opt[j][i]){flag = false; break;}
110 if(!~cur)cur = opt[i][j];
111 else if(opt[i][j] != cur)flag = false;
112 }
113 }
114 }if(flag)legal[S1] += Node{S2, cur};
115 }
116 // for(int S = 1; S <= Smx; ++S)for(auto S2 : legal[S]){
117 // cout << bitset < 5 >(S) << "with" << bitset < 5 >(S2.S) << " col is" << S2.col << endl;
118 // }
119 TreeDP();
120 // for(int i = 1; i <= N; ++i)for(int S = 1; S <= Smx; ++S)for(int j = 1; j <= K; ++j)
121 // cout << "dp[" << i << "][" << j << "][" << bitset < 5 >(S) << "] = " << dp[i][S][j] << endl;
122 ll ans(0);
123 for(int S = 1; S <= Smx; ++S)for(int i = 1; i <= K; ++i)(ans += dp[1][S][i]) %= MOD;
124 printf("%lld\n", ans);
125 }
126 fprintf(stderr, "Time: %.6lf\n", (double)clock() / CLOCKS_PER_SEC);
127 return 0;
128}
129
130template < typename T >
131inline T read(void){
132 T ret(0);
133 int flag(1);
134 char c = getchar();
135 while(c != '-' && !isdigit(c))c = getchar();
136 if(c == '-')flag = -1, c = getchar();
137 while(isdigit(c)){
138 ret *= 10;
139 ret += int(c - '0');
140 c = getchar();
141 }
142 ret *= flag;
143 return ret;
144}
145
146/*
147
1482
1495 2
1501 2
1512 1
1521 2 1 4
1535 2
1541 2
1551 1
1561 2 1 4
157
158*/
提供一种复杂度正确但常数巨大码量较大的并不优秀的无脑做法,思路来自于模拟赛赛时口糊的,在 Luogu 上可以通过,但赛时在 LemonLime 测的时候大概是因为常数原因被卡的就剩
首先我们不难想到
然后呢最开始我看这道题没太仔细,以为
于是在我发现问题后就尝试优化这个思路,最终的过程大概是这样的:
首先树剖显然,然后线段树上维护区间的不可重复的前 +
,实现上用一个 basic_string
存子节点所有值然后排序并各种特判细节做一下即可,不难发现超大的常数就是卡在这里了,这东西某种意义上来讲可以认为其为
然后修改较为简单不再赘述,对于查询直接按照树剖查询并合并,对于不能重复的前 -1
。然后我们要再次查询整棵树的结果,在可重复两次的前
当然这里也浅提一下,如果用 multiset
维护
xxxxxxxxxx
1921
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
25struct Edge{
26 Edge* nxt;
27 int to;
28 OPNEW;
29}ed[210000];
30ROPNEW;
31Edge* head[110000];
32
33int N, Q;
34ll w[110000];
35int dep[110000], dfn[110000], hson[110000], siz[110000], ffa[110000], tp[110000], idx[110000];
36
37void dfs_pre(int p = 1, int fa = 0){
38 dep[p] = dep[fa] + 1;
39 siz[p] = 1;
40 ffa[p] = fa;
41 for(auto i = head[p]; i; i = i->nxt){
42 if(SON == fa)continue;
43 dfs_pre(SON, p);
44 siz[p] += siz[SON];
45 if(siz[hson[p]] < siz[SON])hson[p] = SON;
46 }
47}
48void dfs_make(int p = 1, int top = 1){
49 tp[p] = top;
50 static int cdfn(0);
51 dfn[p] = ++cdfn;
52 idx[cdfn] = p;
53 if(hson[p])dfs_make(hson[p], top);
54 for(auto i = head[p]; i; i = i->nxt)
55 if(SON != ffa[p] && SON != hson[p])
56 dfs_make(SON, SON);
57}
58
59struct Node{
60 ll v[6], vu[6]; //v_max_with_2, v_unique
61 Node(void){memset(v, 0, sizeof v), memset(vu, 0, sizeof vu);}
62 friend Node operator + (const Node &a, const Node &b){
63 Node ret;
64 basic_string < ll > values;
65 for(int i = 1; i <= 5; ++i){
66 if(a.v[i])values += a.v[i];
67 if(b.v[i])values += b.v[i];
68 }sort(values.begin(), values.end(), greater < ll >());
69 for(auto it = values.begin(); it != values.end() && next(it) != values.end() && next(it, 2) != values.end();)
70 if(*it == *next(it) && *next(it) == *next(it, 2))it = values.erase(it);
71 else advance(it, 1);
72 for(int i = 1; i <= 5; ++i)
73 ret.v[i] = (int)values.size() >= i ? values.at(i - 1) : 0;
74 values.clear();
75 for(int i = 1; i <= 5; ++i){
76 if(a.vu[i])values += a.vu[i];
77 if(b.vu[i])values += b.vu[i];
78 }sort(values.begin(), values.end(), greater < ll >());
79 values.erase(unique(values.begin(), values.end()), values.end());
80 for(int i = 1; i <= 5; ++i)
81 ret.vu[i] = (int)values.size() >= i ? values.at(i - 1) : 0;
82 return ret;
83 }
84};
85
86class SegTree{
87private:
88 Node mx[110000 << 2];
89
90
91
92public:
93 void Pushup(int p){
94 mx[p] = mx[LS] + mx[RS];
95 }
96 void Build(int p = 1, int gl = 1, int gr = N){
97 if(gl == gr)return mx[p].v[1] = mx[p].vu[1] = w[idx[gl = gr]], void();
98 Build(LS, gl, MID), Build(RS, MID + 1, gr);
99 Pushup(p);
100 }
101 void Modify(int id, int v, int p = 1, int gl = 1, int gr = N){
102 if(gl == gr)return mx[p].v[1] += v, mx[p].vu[1] += v, void();
103 if(id <= MID)Modify(id, v, LS, gl, MID);
104 else Modify(id, v, RS, MID + 1, gr);
105 Pushup(p);
106 }
107 Node Query(int l, int r, int p = 1, int gl = 1, int gr = N){
108 // printf("Querying l = %d, r = %d\n", l, r);
109 if(l <= gl && gr <= r)return mx[p];
110 if(gr < l || r < gl)return Node();
111 return Query(l, r, LS, gl, MID) + Query(l, r, RS, MID + 1, gr);
112 }
113}st;
114
115void Make(int s, int t){
116 Node cur;
117 while(tp[s] != tp[t]){
118 if(dep[tp[s]] < dep[tp[t]])swap(s, t);
119 cur = cur + st.Query(dfn[tp[s]], dfn[s]);
120 s = ffa[tp[s]];
121 }if(dep[s] < dep[t])swap(s, t);
122 cur = cur + st.Query(dfn[t], dfn[s]);
123 if(!cur.vu[1] || !cur.vu[2]){printf("-1\n"); return;}
124 Node ret = st.Query(1, N);
125 basic_string < ll > tmp;
126 for(int i = 1; i <= 5; ++i)if(ret.v[i])tmp += ret.v[i];
127 for(int i = 1; i <= 2; ++i)
128 if(find(tmp.begin(), tmp.end(), cur.vu[i]) != tmp.end())
129 tmp.erase(find(tmp.begin(), tmp.end(), cur.vu[i]));
130 if((int)tmp.size() < 2 || ((int)tmp.size() == 2 && tmp.at(0) == tmp.at(1))){printf("%lld 0\n", cur.vu[2]); return;}
131 if(tmp.size() == 3 && tmp.at(0) == tmp.at(1)){printf("%lld %lld\n", cur.vu[2], tmp.at(2)); return;}
132 printf("%lld %lld\n", cur.vu[2], tmp.at(0) == tmp.at(1) ? tmp.at(2) : tmp.at(1));
133 // for(int i = 1; i <= 5; ++i)printf("mxchain mxvu[%d] = %lld\n", i, cur.vu[i]);
134 // for(int i = 1; i <= 5; ++i)printf("mxtree mxv[%d] = %lld\n", i, ret.v[i]);
135}
136
137int main(){
138 // freopen("game.in", "r", stdin);
139 // freopen("game.out", "w", stdout);
140 N = read();
141 for(int i = 1; i <= N - 1; ++i){
142 int s = read(), t = read();
143 head[s] = new Edge{head[s], t};
144 head[t] = new Edge{head[t], s};
145 }dfs_pre(), dfs_make();
146 for(int i = 1; i <= N; ++i)w[i] = read();
147 st.Build();
148 Q = read();
149 while(Q--){
150 int opt = read(), x = read(), y = read();
151 if(opt == 0)st.Modify(dfn[x], y);
152 else Make(x, y);
153 }
154 fprintf(stderr, "Time: %.6lf\n", (double)clock() / CLOCKS_PER_SEC);
155 return 0;
156}
157
158template < typename T >
159inline T read(void){
160 T ret(0);
161 int flag(1);
162 char c = getchar();
163 while(c != '-' && !isdigit(c))c = getchar();
164 if(c == '-')flag = -1, c = getchar();
165 while(isdigit(c)){
166 ret *= 10;
167 ret += int(c - '0');
168 c = getchar();
169 }
170 ret *= flag;
171 return ret;
172}
173
174/*
175
1767
1771 2
1782 3
1792 5
1801 5
1815 6
1825 7
1835 5 3 2 1 5 3
1846
1851 3 5
1861 2 5
1871 2 1
1880 2 1
1891 2 5
1901 2 1
191
192*/
显然合法区间的一个合法子序列一定可以转换为递增或递减的,于是令
xxxxxxxxxx
1131
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, K;
28ll ans(0);
29ll A[510000];
30unordered_map < int, ll > cnt;
31ll dp[510000];
32
33class SegTree{
34private:
35 ll tr[110000 << 2];
36 int mn[110000 << 2];
37
38
39
40public:
41 SegTree(void){memset(mn, 0x3f, sizeof mn);}
42 void Pushup(int p){
43 tr[p] = tr[LS] + tr[RS];
44 mn[p] = min(mn[LS], mn[RS]);
45 }
46 void Modify(int val, int id, int p = 1, int gl = 1, int gr = MXV){
47 // undel.insert(p);
48 if(gl == gr)return tr[p]++, mn[p] = min(mn[p], id), void();
49 if(val <= MID)Modify(val, id, LS, gl, MID);
50 else Modify(val, id, RS, MID + 1, gr);
51 Pushup(p);
52 }
53 void Assign(int val, int p = 1, int gl = 1, int gr = MXV){
54 tr[p] = 0, mn[p] = 0x3f3f3f3f;
55 if(gl == gr)return;
56 if(val <= MID)Assign(val, LS, gl, MID);
57 else Assign(val, RS, MID + 1, gr);
58 }
59 int QueryMin(int l, int r, int p = 1, int gl = 1, int gr = MXV){
60 if(l <= gl && gr <= r)return mn[p];
61 if(r < gl || gr < l)return 0x3f3f3f3f;
62 return min(QueryMin(l, r, LS, gl, MID), QueryMin(l, r, RS, MID + 1, gr));
63 }
64 ll QueryCnt(int l, int r, int p = 1, int gl = 1, int gr = MXV){
65 if(l <= gl && gr <= r)return tr[p];
66 if(r < gl || gr < l)return 0;
67 return QueryCnt(l, r, LS, gl, MID) + QueryCnt(l, r, RS, MID + 1, gr);
68 }
69}st;
70
71ll Make(void){
72 for(int i = 0; i <= N; ++i)dp[i] = 0;
73 ll ret(0);
74 for(int i = N; i >= 1; --i){
75 int p = st.QueryMin(A[i] + 1, A[i] + K);
76 dp[i] = p == 0x3f3f3f3f ? 0 : dp[p] + st.QueryCnt(A[i] + 1, A[p]);
77 st.Modify(A[i], i);
78 ret += dp[i];
79 }
80 for(int i = 1; i <= N; ++i)st.Assign(A[i]);
81 return ret;
82}
83
84int main(){
85 int T = read();
86 while(T--){
87 ans = 0;
88 N = read(), K = read();
89 for(int i = 1; i <= N; ++i)cnt[A[i] = read()]++;
90 for(auto v : cnt)ans += ((v.second) * (v.second + 1)) >> 1;
91 cnt.clear();
92 ans += Make(), reverse(A + 1, A + N + 1), ans += Make();
93 printf("%lld\n", ans);
94 }
95 fprintf(stderr, "Time: %.6lf\n", (double)clock() / CLOCKS_PER_SEC);
96 return 0;
97}
98
99template < typename T >
100inline T read(void){
101 T ret(0);
102 int flag(1);
103 char c = getchar();
104 while(c != '-' && !isdigit(c))c = getchar();
105 if(c == '-')flag = -1, c = getchar();
106 while(isdigit(c)){
107 ret *= 10;
108 ret += int(c - '0');
109 c = getchar();
110 }
111 ret *= flag;
112 return ret;
113}
考虑发现,若两区间存在包含关系,即
xxxxxxxxxx
941
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
24
25template < typename T = int >
26inline T read(void);
27
28int N, Q;
29int dp[210000][25];
30struct Range{
31 int l, r;
32 friend const bool operator < (const Range &a, const Range &b){
33 return a.l == b.l ? a.r > b.r : a.l < b.l;
34 }
35}rngt[210000];
36basic_string < Range > rng;
37
38int main(){
39 N = read(), Q = read();
40 for(int i = 1; i <= N; ++i)rngt[i].l = read(), rngt[i].r = read();
41 sort(rngt + 1, rngt + N + 1);
42 int curR(INF);
43 for(int i = N; i >= 1; --i){
44 if(rngt[i].r >= curR)continue;
45 curR = rngt[i].r;
46 rng += rngt[i];
47 }sort(rng.begin(), rng.end());
48 int tot = rng.size();
49 int nxt(1);
50 for(int cur = 1; cur <= tot; ++cur){
51 while(nxt <= tot && rng(nxt).l <= rng(cur).r)++nxt;
52 dp[cur][0] = nxt;
53 }for(int i = 0; i <= 20; ++i)dp[tot + 1][i] = tot + 1;
54 for(int j = 1; j <= 20; ++j)
55 for(int i = 1; i <= tot; ++i)
56 dp[i][j] = dp[dp[i][j - 1]][j - 1];
57 while(Q--){
58 int l = read(), r = read();
59 auto it = lower_bound(rng.begin(), rng.end(), Range{l, INF});
60 if(it == rng.end() || it->l != l){printf("0\n"); continue;}
61 if(it->r == r){printf("998244352\n"); continue;}
62 auto nxt = lower_bound(rng.begin(), rng.end(), Range{l + 1, INF});
63 if(nxt == rng.end() || nxt->l > it->r || nxt->r > r){printf("0\n"); continue;}
64 int cur = distance(rng.begin(), it) + 1;
65 int cnxt = distance(rng.begin(), nxt) + 1;
66 bool ret(0);
67 for(int j = 20; j >= 0; --j)
68 if(dp[cur][j] <= tot && rng(dp[cur][j]).r <= r)
69 cur = dp[cur][j], ret ^= j ? 0 : 1;
70 for(int j = 20; j >= 0; --j)
71 if(dp[cnxt][j] <= tot && rng(dp[cnxt][j]).r <= r)
72 cnxt = dp[cnxt][j], ret ^= j ? 0 : 1;
73 if(cur == cnxt || (rng(cur).r != r && rng(cnxt).r != r)){printf("0\n"); continue;}
74 printf("%d\n", ret ? 998244352 : 1);
75 }
76 fprintf(stderr, "Time: %.6lf\n", (double)clock() / CLOCKS_PER_SEC);
77 return 0;
78}
79
80template < typename T >
81inline T read(void){
82 T ret(0);
83 int flag(1);
84 char c = getchar();
85 while(c != '-' && !isdigit(c))c = getchar();
86 if(c == '-')flag = -1, c = getchar();
87 while(isdigit(c)){
88 ret *= 10;
89 ret += int(c - '0');
90 c = getchar();
91 }
92 ret *= flag;
93 return ret;
94}
update-2023_01_17 初稿