LG-P8280 「MCOI-08」Photoelectric Effect。
有一棵
请问有多少个方案对所有点染色,使得当点对
答案对
一个较为显然的 树形DP + 状压DP,复杂度卡的比较满,细节巨多,但是思路较为显然,赛时写了 !head[p]->nxt 把根也当成叶子了,也就是如果根只有一个子树那就会寄掉。
然后还有个问题就是 Luogu 上必须把边数开到
当然这里的代码是赛时不太正确的,AC Code 参考下文。
xxxxxxxxxx152123
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
222324
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
14221435 21441 21452 11461 2 1 41475 21481 21491 11501 2 1 4151
152*/给定 -1。
写了篇题解,内容就放在下文了,错的点是没有考虑到应该维护前
xxxxxxxxxx193123
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
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_unique63 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
17771781 21792 31802 41811 51825 61835 71845 4 3 2 1 4 318561861 3 41871 2 51881 2 11890 2 11901 2 51911 2 1192
193*/给定一个
请求出所有合法的子区间数量。多组数据,
不会,跳!
给定
赛时没想出来,确实是一道人类智慧性质题,很有 AGC 的感觉,赛时糊的暴力也挂了。
xxxxxxxxxx79123
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
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}上文说的差不多了。
xxxxxxxxxx158123
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
222324
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
14821495 21501 21512 11521 2 1 41535 21541 21551 11561 2 1 4157
158*/提供一种复杂度正确但常数巨大码量较大的并不优秀的无脑做法,思路来自于模拟赛赛时口糊的,在 Luogu 上可以通过,但赛时在 LemonLime 测的时候大概是因为常数原因被卡的就剩
首先我们不难想到
然后呢最开始我看这道题没太仔细,以为
于是在我发现问题后就尝试优化这个思路,最终的过程大概是这样的:
首先树剖显然,然后线段树上维护区间的不可重复的前 +,实现上用一个 basic_string 存子节点所有值然后排序并各种特判细节做一下即可,不难发现超大的常数就是卡在这里了,这东西某种意义上来讲可以认为其为
然后修改较为简单不再赘述,对于查询直接按照树剖查询并合并,对于不能重复的前 -1。然后我们要再次查询整棵树的结果,在可重复两次的前
当然这里也浅提一下,如果用 multiset 维护
xxxxxxxxxx192123
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
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_unique61 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
17671771 21782 31792 51801 51815 61825 71835 5 3 2 1 5 318461851 3 51861 2 51871 2 11880 2 11891 2 51901 2 1191
192*/显然合法区间的一个合法子序列一定可以转换为递增或递减的,于是令
xxxxxxxxxx113123
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, 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}考虑发现,若两区间存在包含关系,即
xxxxxxxxxx94123
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
222324
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 初稿