bzoj3159: 决战
呀智障选手都快忘了代码怎么打了..
做这道题干啥咧..
GDOI2017D3T4.. dwjshift说很像这道题,然后就去做了..
然后就做了半个月??
简略解法
就是两棵LCT,一棵维护树的结构,一棵维护权值,两棵树在中序遍历上映射,所以维护一下根对根的映射即可
所以要怎么Access..
对于当前点$x$,在把它旋到当前splay的根的时候可以知道它在这棵splay上的排名
然后就去找对应的那棵权值splay的排名就知道映射的是哪个了啊..
然后.. 就没有然后了吧..
下面是代码呀..
#include <cstdio> #include <cstring> #include <cstdlib> #include <algorithm> #define LL long long using namespace std; const LL Maxn = 50010; struct node { LL y, next; }a[Maxn*2]; LL first[Maxn], len; LL _max(LL x, LL y) { return x > y ? x : y; } LL _min(LL x, LL y) { return x < y ? x : y; } void ins(LL x, LL y) { len++; a[len].y = y; a[len].next = first[x]; first[x] = len; } LL n, m, r; LL p[Maxn]; LL Maxx[Maxn], Minn[Maxn], sum[Maxn], val[Maxn]; LL vfa[Maxn], fa[Maxn], sizef[Maxn], sizev[Maxn]; LL cf[Maxn][2], cv[Maxn][2]; LL revf[Maxn], revv[Maxn], la[Maxn]; LL sta[Maxn], tp; char s[10]; void dfs(LL x) { p[x] = x; sizef[x] = sizev[x] = 1; for(LL k = first[x]; k; k = a[k].next){ LL y = a[k].y; if(y == fa[x]) continue; fa[y] = x; vfa[y] = x; dfs(y); } } LL rt; /*f*/ bool is_rootf(LL x) { return cf[fa[x]][0] != x && cf[fa[x]][1] != x; } void push_downf(LL x) { if(revf[x]){ swap(cf[x][0], cf[x][1]); revf[cf[x][0]] ^= 1; revf[cf[x][1]] ^= 1; revf[x] = 0; } } void prepf(LL x) { LL i; tp = 0; for(i = x; !is_rootf(i); i = fa[i]) sta[++tp] = i; sta[++tp] = i; for(i = tp; i >= 1; i--) push_downf(sta[i]); } void updatef(LL x) { sizef[x] = sizef[cf[x][0]]+sizef[cf[x][1]]+1; } void rotatef(LL x) { LL y = fa[x], z = fa[y], l, r; if(cf[y][0] == x) l = 0; else l = 1; r = l^1; if(!is_rootf(y)){ if(cf[z][0] == y) cf[z][0] = x; else cf[z][1] = x; } fa[x] = z; fa[y] = x; fa[cf[x][r]] = y; cf[y][l] = cf[x][r]; cf[x][r] = y; updatef(y); } void splayf(LL x) { rt = x; prepf(x); while(!is_rootf(x)){ LL y = fa[x], z = fa[y]; if(!is_rootf(y)){ if(is_rootf(z)) rt = z; if((cf[z][0] == y)^(cf[y][0] == x)) rotatef(x); else rotatef(y); } else rt = y; rotatef(x); } updatef(x); } /*v*/ bool is_rootv(LL x) { return cv[vfa[x]][0] != x && cv[vfa[x]][1] != x; } void push_downv(LL x) { if(revv[x]){ swap(cv[x][0], cv[x][1]); revv[cv[x][0]] ^= 1; revv[cv[x][1]] ^= 1; revv[x] = 0; } if(la[x] > 0){ if(cv[x][0] > 0){ sum[cv[x][0]] += sizev[cv[x][0]]*la[x]; val[cv[x][0]] += la[x]; Maxx[cv[x][0]] += la[x]; Minn[cv[x][0]] += la[x]; la[cv[x][0]] += la[x]; } if(cv[x][1] > 0){ sum[cv[x][1]] += sizev[cv[x][1]]*la[x]; val[cv[x][1]] += la[x]; Maxx[cv[x][1]] += la[x]; Minn[cv[x][1]] += la[x]; la[cv[x][1]] += la[x]; } la[x] = 0; } } void prepv(LL x) { LL i; tp = 0; for(i = x; !is_rootv(i); i = vfa[i]) sta[++tp] = i; sta[++tp] = i; for(i = tp; i >= 1; i--) push_downv(sta[i]); } void updatev(LL x) { Maxx[x] = _max(Maxx[cv[x][0]], _max(Maxx[cv[x][1]], val[x])); Minn[x] = _min(Minn[cv[x][0]], _min(Minn[cv[x][1]], val[x])); sum[x] = sum[cv[x][0]]+sum[cv[x][1]]+val[x]; sizev[x] = sizev[cv[x][0]]+sizev[cv[x][1]]+1; } void rotatev(LL x) { LL y = vfa[x], z = vfa[y], l, r; if(cv[y][0] == x) l = 0; else l = 1; r = l^1; if(!is_rootv(y)){ if(cv[z][0] == y) cv[z][0] = x; else cv[z][1] = x; } vfa[x] = z; vfa[y] = x; vfa[cv[x][r]] = y; cv[y][l] = cv[x][r]; cv[x][r] = y; updatev(y); } void splayv(LL x) { prepv(x); while(!is_rootv(x)){ LL y = vfa[x], z = vfa[y]; if(!is_rootv(y)){ if((cv[z][0] == y)^(cv[y][0] == x)) rotatev(x); else rotatev(y); } rotatev(x); } updatev(x); } LL find_rank(LL x, LL p) { push_downv(x); if(sizev[cv[x][0]]+1 == p) return x; if(sizev[cv[x][0]] >= p) return find_rank(cv[x][0], p); else return find_rank(cv[x][1], p-sizev[cv[x][0]]-1); } void splay(LL x) { splayf(x); LL o = find_rank(p[rt], sizef[cf[x][0]]+1); splayv(o); p[x] = o; } void access(LL x) { LL tf = 0, tv = 0; while(x){ splay(x); LL o = p[x]; p[cf[x][1]] = cv[o][1]; cf[x][1] = tf; cv[o][1] = tv; if(tv) vfa[tv] = o; tv = o; tf = x; x = fa[x]; } } void make_root(LL x) { access(x); splay(x); revf[x] ^= 1; revv[p[x]] ^= 1; } void getchain(LL x, LL y) { make_root(x); access(y); splay(y); } LL getsum(LL x, LL y) { getchain(x, y); return sum[p[y]]; } LL getmin(LL x, LL y) { getchain(x, y); return Minn[p[y]]; } LL getmax(LL x, LL y) { getchain(x, y); return Maxx[p[y]]; } void add(LL x, LL y, LL c) { getchain(x, y); sum[p[y]] += sizev[p[y]]*c; val[p[y]] += c; Maxx[p[y]] += c; Minn[p[y]] += c; la[p[y]] += c; } void invert(LL x, LL y) { getchain(x, y); revv[p[y]] ^= 1; } int main() { LL i, j, k; Maxx[0] = -0x7fffffff; Minn[0] = 0x7fffffff; scanf("%lld%lld%lld", &n, &m, &r); for(i = 1; i < n; i++){ LL x, y; scanf("%lld%lld", &x, &y); ins(x, y); ins(y, x); } dfs(r); for(i = 1; i <= m; i++){ scanf("%s", s+1); if(s[1] == 'I' && s[3] == 'c'){ LL x, y, c; scanf("%lld%lld%lld", &x, &y, &c); add(x, y, c); } else if(s[1] == 'S'){ LL x, y; scanf("%lld%lld", &x, &y); printf("%lld\n", getsum(x, y)); } else if(s[1] == 'M' && s[2] == 'a'){ LL x, y; scanf("%lld%lld", &x, &y); printf("%lld\n", getmax(x, y)); } else if(s[1] == 'M'){ LL x, y; scanf("%lld%lld", &x, &y); printf("%lld\n", getmin(x, y)); } else { LL x, y; scanf("%lld%lld", &x, &y); invert(x, y); } } return 0; }
作者:Ra1nbow
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。