杂题小记(2023.03.07)更好的阅读体验戳此进入LG-P4556 [Vani有约会]雨天的尾巴 /【模板】线段树合并LG-P5494 【模板】线段树分裂LG-P4005 小 Y 和地铁LOJ #2323. 「清华集训 2017」小 Y 和地铁UPD
标准线段树合并板子,注意每次修改存在四次 Modify 对于 Node 的数组需要开更大一些。
xxxxxxxxxx149123
4567891011
12using namespace std;13
14mt19937 rnd(random_device{}());15int rndd(int l, int r){return rnd() % (r - l + 1) + l;}16bool rnddd(int x){return rndd(1, 100) <= x;}17
18typedef unsigned int uint;19typedef unsigned long long unll;20typedef long long ll;21typedef long double ld;22
2324
25template < typename T = int >26inline T read(void);27
28struct Node{29 30 31 Node* ls, *rs;32 int val, cnt;33 OPNEW;34}nd[LIM << 6];35ROPNEW_NODE;36
37void Pushup(Node* p){38 if(!p)return;39 if(cnt(p->ls) >= cnt(p->rs))p->val = val(p->ls), p->cnt = cnt(p->ls);40 else p->val = val(p->rs), p->cnt = cnt(p->rs);41}42
43class SegTree{44private:45 46 47 48public:49 Node* root;50 void Modify(int idx, int v, Node* &p, int gl = 1, int gr = LIM){51 if(!p)p = new Node{npt, npt, 0, 0};52 if(gl == gr)return p->cnt += v, p->val = p->cnt ? gl = gr : 0, void();53 if(idx <= MID)Modify(idx, v, p->ls, gl, MID);54 else Modify(idx, v, p->rs, MID + 1, gr);55 Pushup(p);56 }57 int Query(void){58 return val(root);59 }60}st[LIM];61
62Node* Merge(Node* A, Node* B, int gl = 1, int gr = LIM){63 if(!A || !B)return A ? A : B;64 if(gl == gr)return A->cnt += B->cnt, A->val = A->cnt ? gl = gr : 0, A;65 if(!A->ls && B->ls)A->ls = B->ls;66 else A->ls = Merge(A->ls, B->ls, gl, MID);67 if(!A->rs && B->rs)A->rs = B->rs;68 else A->rs = Merge(A->rs, B->rs, MID + 1, gr);69 return Pushup(A), A;70}71
72int N, M;73
74struct Edge{75 Edge* nxt;76 int to;77 OPNEW;78}ed[LIM << 1];79ROPNEW;80Edge* head[LIM];81
82int dep[LIM], dfn[LIM], idx[LIM], top[LIM], hson[LIM], siz[LIM], fa[LIM];83
84void dfs_pre(int p = 1, int fa = 0){85 ::fa[p] = fa, dep[p] = dep[fa] + 1, siz[p] = 1;86 for(auto i = head[p]; i; i = i->nxt){87 if(SON == fa)continue;88 dfs_pre(SON, p);89 siz[p] += siz[SON];90 if(siz[SON] > siz[hson[p]])hson[p] = SON;91 }92}93void dfs_make(int p = 1, int top = 1){94 static int cdfn(0);95 dfn[p] = ++cdfn, idx[cdfn] = p;96 ::top[p] = top;97 if(hson[p])dfs_make(hson[p], top);98 for(auto i = head[p]; i; i = i->nxt)99 if(SON != fa[p] && SON != hson[p])dfs_make(SON, SON);100}101int LCA(int s, int t){102 while(top[s] != top[t]){103 if(dep[top[s]] < dep[top[t]])swap(s, t);104 s = fa[top[s]];105 }if(dep[s] < dep[t])swap(s, t);106 return t;107}108
109int ans[LIM];110
111void dfs_merge(int p = 1, int fa = 0){112 for(auto i = head[p]; i; i = i->nxt)113 if(SON != fa)dfs_merge(SON, p), st[p].root = Merge(st[p].root, st[SON].root);114 ans[p] = st[p].Query();115}116
117int main(){118 N = read(), M = read();119 for(int i = 1; i <= N - 1; ++i){120 int s = read(), t = read();121 head[s] = new Edge{head[s], t};122 head[t] = new Edge{head[t], s};123 }dfs_pre(), dfs_make();124 for(int i = 1; i <= M; ++i){125 int s = read(), t = read(), v = read(), lca = LCA(s, t);126 // printf("s = %d, t = %d, lca = %d\n", s, t, lca);127 st[s].Modify(v, 1, st[s].root), st[t].Modify(v, 1, st[t].root);128 st[lca].Modify(v, -1, st[lca].root), st[fa[lca]].Modify(v, -1, st[fa[lca]].root);129 }dfs_merge();130 for(int i = 1; i <= N; ++i)printf("%d\n", ans[i]);131 fprintf(stderr, "Time: %.6lf\n", (double)clock() / CLOCKS_PER_SEC);132 return 0;133}134
135template < typename T >136inline T read(void){137 T ret(0);138 int flag(1);139 char c = getchar();140 while(c != '-' && !isdigit(c))c = getchar();141 if(c == '-')flag = -1, c = getchar();142 while(isdigit(c)){143 ret *= 10;144 ret += int(c - '0');145 c = getchar();146 }147 ret *= flag;148 return ret;149}线段树分裂模板,注意对于查询 rank 时需要考虑到 gl = gr 的点中可能有多个相同权值的点。
xxxxxxxxxx137123
4567891011
12using namespace std;13
14mt19937 rnd(random_device{}());15int rndd(int l, int r){return rnd() % (r - l + 1) + l;}16bool rnddd(int x){return rndd(1, 100) <= x;}17
18typedef unsigned int uint;19typedef unsigned long long unll;20typedef long long ll;21typedef long double ld;22
2324
25template < typename T = int >26inline T read(void);27
28struct Node{29 Node *ls, *rs;30 ll cnt;31 OPNEW;32}nd[LIM << 5];33ROPNEW_NODE;34Node* root[LIM];35
3637383940
41void Pushup(Node* p){42 if(!p)return;43 p->cnt = cnt(p->ls) + cnt(p->rs);44}45void Modify(int idx, int val, Node* &p, int gl = 1, int gr = LIM){46 if(!p)p = new Node{npt, npt, 0};47 if(gl == gr)return p->cnt += val, void();48 if(idx <= MID)Modify(idx, val, p->ls, gl, MID);49 else Modify(idx, val, p->rs, MID + 1, gr);50 Pushup(p);51}52ll QueryCnt(int l, int r, Node* p, int gl = 1, int gr = LIM){53 if(!p || gr < l || gl > r)return 0;54 if(l <= gl && gr <= r)return p->cnt;55 return QueryCnt(l, r, p->ls, gl, MID) + QueryCnt(l, r, p->rs, MID + 1, gr);56}57ll QueryByRnk(ll rnk, Node* p, int gl = 1, int gr = LIM){58 // printf("Querying rnk = %lld, gl = %d, gr = %d, cnt = %lld\n", rnk, gl, gr, cnt(p));59 if(!p)return -1;60 if(gl == gr)return rnk <= cnt(p) ? gl = gr : -1;61 if(rnk <= cnt(p->ls))return QueryByRnk(rnk, p->ls, gl, MID);62 else return QueryByRnk(rnk - cnt(p->ls), p->rs, MID + 1, gr);63}64Node* Merge(Node* A, Node* B, int gl = 1, int gr = LIM){65 if(!A || !B)return A ? A : B;66 if(gl == gr)return A->cnt += B->cnt, A;67 if(!A->ls && B->ls)A->ls = B->ls;68 else A->ls = Merge(A->ls, B->ls, gl, MID);69 if(!A->rs && B->rs)A->rs = B->rs;70 else A->rs = Merge(A->rs, B->rs, MID + 1, gr);71 return Pushup(A), A;72}73Node* Split(Node* &S, int val, int gl = 1, int gr = LIM){74 if(!S)return npt;75 Node* np = new Node{npt, npt, 0};76 if(val <= MID)return np->rs = S->rs, S->rs = npt, np->ls = Split(S->ls, val, gl, MID), Pushup(S), Pushup(np), np;77 else if(val == MID + 1)return np->rs = S->rs, S->rs = npt, Pushup(S), Pushup(np), np;78 else return np->rs = Split(S->rs, val, MID + 1, gr), Pushup(S), Pushup(np), np;79}80
81int N, M;82int cur(1);83
84int main(){85 N = read(), M = read();86 for(int i = 1; i <= N; ++i)Modify(i, read(), root[cur]);87 while(M--){88 int opt = read();89 switch(opt){90 case 0:{91 int idx = read(), l = read(), r = read();92 Node *L = Split(root[idx], l), *R = Split(L, r + 1);93 root[++cur] = L, root[idx] = Merge(root[idx], R);94 // printf("origin : %lld, split : %lld\n", QueryCnt(1, LIM, root[idx]), QueryCnt(1, LIM, root[cur]));95 break;96 }97 case 1:{98 int t = read(), s = read();99 root[t] = Merge(root[t], root[s]);100 break;101 }102 case 2:{103 int idx = read(), cnt = read(), val = read();104 Modify(val, cnt, root[idx]);105 break;106 }107 case 3:{108 int idx = read(), l = read(), r = read();109 printf("%lld\n", QueryCnt(l, r, root[idx]));110 break;111 }112 case 4:{113 int idx = read(); ll rnk = read < ll >();114 printf("%lld\n", QueryByRnk(rnk, root[idx]));115 break;116 }117 }118 }119 fprintf(stderr, "Time: %.6lf\n", (double)clock() / CLOCKS_PER_SEC);120 return 0;121}122
123template < typename T >124inline T read(void){125 T ret(0);126 int flag(1);127 char c = getchar();128 while(c != '-' && !isdigit(c))c = getchar();129 if(c == '-')flag = -1, c = getchar();130 while(isdigit(c)){131 ret *= 10;132 ret += int(c - '0');133 c = getchar();134 }135 ret *= flag;136 return ret;137}找一下性质,发现对于只有一个交点的站点一定无贡献,对于有且仅有两个交点的考虑发现其有效状态只有四种(即发现对于从线段的左端点与右端点绕过是等效的),于是考虑随机一个初始状态后
xxxxxxxxxx142123
4567891011
12using namespace std;13
14mt19937 rnd(random_device{}());15int rndd(int l, int r){return rnd() % (r - l + 1) + l;}16bool rnddd(int x){return rndd(1, 100) <= x;}17
18typedef unsigned int uint;19typedef unsigned long long unll;20typedef long long ll;21typedef long double ld;22
2324
25template < typename T = int >26inline T read(void);27
28int N;29int pos[50];30int status[50];31bool itsc[50][50];32int cur(0);33int ans(INT_MAX);34struct Line{int l, r;};35basic_string < Line > lines;36
37int main(){38 auto notIntersect = [](int a, int b)->bool{39 if(line(a).l > line(b).l)swap(a, b);40 switch(status[a]){41 case 1:{42 switch(status[b]){43 case 1: return line(a).r < line(b).l || line(b).r < line(a).r;44 case 2: return true;45 case 3: return line(b).l > line(a).r;46 case 4: return line(b).r > line(a).r;47 }break;48 }49 case 2:{50 switch(status[b]){51 case 1: return true;52 case 2: return line(a).r < line(b).l || line(b).r < line(a).r;53 case 3: return line(b).r > line(a).r;54 case 4: return line(b).l > line(a).r;55 }break;56 }57 case 3:{58 switch(status[b]){59 case 1: return true;60 case 2: return line(b).r < line(a).r || line(b).l > line(a).r;61 case 3: return line(b).r > line(a).r;62 case 4: return line(b).l > line(a).r;63 }break;64 }65 case 4:{66 switch(status[b]){67 case 1: return line(b).r < line(a).r || line(b).l > line(a).r;68 case 2: return true;69 case 3: return line(b).l > line(a).r;70 case 4: return line(b).r > line(a).r;71 }break;72 }73 }return false;74 };75 auto Intersect = [notIntersect](int i, int j)->bool{return !notIntersect(i, j);};//判断写反了,懒的改就写了个 notIntersect 转一下。。。。。。76 auto SetOrigin = [Intersect](void)->void{77 cur = 0;78 for(int i = 1; i <= N; ++i)for(int j = i + 1; j <= N; ++j)cur += (itsc[i][j] = itsc[j][i] = Intersect(i, j));//, printf("checking i = %d, j = %d, res = %d\n", i, j, itsc[i][j] ? 1 : 0);79 ans = min(ans, cur);80 };81 auto Anneal = [Intersect](void)->void{82 double T = 50.0, delta = 0.993;83 while(T > 1e-2){84 int idx = rndd(1, N);85 int val = rndd(1, 4);86 while(val == status[idx])val = rndd(1, 4);87 int nxt = cur;88 int lsts = status[idx]; status[idx] = val;89 for(int i = 1; i <= N; ++i)if(i != idx){90 if(itsc[idx][i] && !Intersect(idx, i))--nxt;91 else if(!itsc[idx][i] && Intersect(idx, i))++nxt;92 }93 if(nxt < cur || exp(-(double)(nxt - cur) / T) > (double)rndd(1, 114514) / 114514){94 cur = nxt;95 ans = min(ans, cur);96 for(int i = 1; i <= N; ++i)if(i != idx)itsc[idx][i] = itsc[i][idx] = Intersect(idx, i);97 }else status[idx] = lsts;98 T *= delta;99 }100 };101 int T = read();102 while(T--){103 memset(pos, 0, sizeof pos);104 memset(status, 0, sizeof status);105 lines.clear();106 ans = INT_MAX;107 N = read();108 for(int i = 1; i <= N; ++i){109 int val = read();110 if(pos[val])lines += Line{min(pos[val], i), max(pos[val], i)};111 else pos[val] = i;112 }N = lines.size();113 if(!N){printf("0\n"); continue;}114 int t = 30;115 while(t--){116 memset(itsc, 0, sizeof itsc);117 for(int i = 1; i <= N; ++i)status[i] = rndd(1, 4);118 // for(int i = 1; i <= N; ++i)printf("%d ", status[i]);119 // printf("\n");120 SetOrigin();121 Anneal();122 }printf("%d\n", ans);123 }124 fprintf(stderr, "Time: %.6lf\n", (double)clock() / CLOCKS_PER_SEC);125 return 0;126}127
128template < typename T >129inline T read(void){130 T ret(0);131 int flag(1);132 char c = getchar();133 while(c != '-' && !isdigit(c))c = getchar();134 if(c == '-')flag = -1, c = getchar();135 while(isdigit(c)){136 ret *= 10;137 ret += int(c - '0');138 c = getchar();139 }140 ret *= flag;141 return ret;142}update-2023_03_07 初稿