BZOJ 1036 树的统计 树链剖分or link-cut-tree
崩溃,从上个星期开始BZOJ就一直RE,死命RE,写什么都能RE,心好累。还好吧!算了,不管它。幸亏有师兄,把那个测试数据给我测了一下,否则我都快抑郁了。加油吧!
这道题就是一个模版题了,不过也学了点东西,比如写线段树时,数组要开到4倍。
接下来没办法了,只能是我RE的代码了。(如果有大神知道哪里RE了,麻烦告知一声)。
1 #include<cstdio> 2 #include<iostream> 3 #include<vector> 4 #define rep(i,j,k) for(int i = j; i <= k; i++) 5 #define maxn 300500 6 #define INF 0x7fffffff 7 using namespace std; 8 9 int n, key[maxn] = {0}; 10 vector<int> q[maxn]; 11 12 int pa[maxn] = {0}, son[maxn] = {0}, size[maxn] = {0}, top[maxn] = {0}; 13 int dep[maxn] = {0}, w[maxn] = {0}, tot = 0, maxl = -INF; 14 15 void dfs(int now) 16 { 17 son[now] = 0; 18 size[now] = 1; 19 int s = q[now].size(); 20 rep(i,0,s-1) 21 { 22 int to = q[now][i]; 23 if( to == pa[now] ) continue; 24 pa[to] = now; 25 dep[to] = dep[now] + 1; 26 dfs(to); 27 size[now] += size[to]; 28 if( size[to] > size[son[now]] ) son[now] = to; 29 } 30 } 31 32 void dfs2(int now,int ph) 33 { 34 top[now] = ph; 35 w[now] = ++tot; 36 if( son[now] ) dfs2(son[now],ph); 37 int s = q[now].size(); 38 rep(i,0,s-1) 39 { 40 int y = q[now][i]; 41 if( y != son[now] && y != pa[now] ) dfs2(y,y); 42 } 43 } 44 45 struct node{ 46 int l, r, maxl, sum; 47 node(){ 48 l = r = maxl = sum = 0; 49 } 50 }; 51 node nod[maxn*4]; 52 53 void yuchu(int l,int r,int num) 54 { 55 nod[num].l = l, nod[num].r = r; 56 if( l == r ){ 57 nod[num].maxl = nod[num].sum = key[l]; 58 return; 59 } 60 int mid = (l+r) / 2; 61 yuchu(l,mid,num*2); 62 yuchu(mid+1,r,num*2+1); 63 nod[num].maxl = max(nod[num*2].maxl,nod[num*2+1].maxl); 64 nod[num].sum = nod[num*2].sum + nod[num*2+1].sum; 65 } 66 67 void update(int po,int key,int num) 68 { 69 int l = nod[num].l, r = nod[num].r; 70 if( l == r ){ 71 nod[num].sum = nod[num].maxl = key; 72 return; 73 } 74 int mid = (l+r) / 2; 75 if( po <= mid ){ 76 update(po,key,num*2); 77 } 78 else { 79 update(po,key,num*2+1); 80 } 81 nod[num].maxl = max(nod[num*2].maxl,nod[num*2+1].maxl); 82 nod[num].sum = nod[num*2].sum + nod[num*2+1].sum; 83 } 84 85 int qure(int ll,int rr,int num) 86 { 87 int l = nod[num].l, r = nod[num].r; 88 if( l>=ll && rr >= r ){ 89 if( nod[num].maxl > maxl ) maxl = nod[num].maxl; 90 return nod[num].sum; 91 } 92 int mid = (l+r) / 2; 93 if( rr <= mid ){ 94 return qure(ll,rr,num*2); 95 } 96 else if( ll > mid ){ 97 return qure(ll,rr,num*2+1); 98 } 99 else if( ll <= mid && rr > mid ){ 100 return qure(ll,mid,num*2) + qure(mid+1,rr,num*2+1); 101 } 102 } 103 104 int quire(int x,int y,int pan) 105 { 106 int ans = 0; 107 maxl = -INF; 108 while( top[x] != top[y] ){ 109 if( dep[top[x]] < dep[top[y]] ){ 110 swap(x,y); 111 } 112 ans += qure(w[top[x]],w[x],1); 113 x = pa[top[x]]; 114 } 115 if( dep[x] > dep[y] ) swap(x,y); 116 ans += qure(w[x],w[y],1); 117 if( pan ) return maxl; 118 else return ans; 119 } 120 121 int main() 122 { 123 scanf("%d", &n); 124 int x, y; 125 rep(i,1,n-1){ 126 scanf("%d %d", &x, &y); 127 q[x].push_back(y); 128 q[y].push_back(x); 129 } 130 dfs(1); 131 dfs2(1,1); 132 rep(i,1,n){ 133 scanf("%d", &key[w[i]]); 134 } 135 yuchu(1,tot,1); 136 int q, key; 137 scanf("%d", &q); char c[7] = {0}; 138 rep(i,1,q){ 139 scanf("%s", c); 140 if( c[0] == 'Q' ){ 141 if( c[1] == 'S' ){ 142 scanf("%d %d", &x, &y); 143 cout<<quire(x,y,0)<<endl; 144 } 145 else if( c[1] == 'M' ){ 146 scanf("%d %d", &x, &y); 147 cout<<quire(x,y,1)<<endl; 148 } 149 } 150 else if( c[0] == 'C' ){ 151 scanf("%d %d", &x, &key); 152 update(w[x],key,1); 153 } 154 } 155 return 0; 156 }
link-cut-tree 版本这是我一直想学的数据结构,(这个坑已经挖了好久了,直到这个星期才开始填,还好填了大半,虽然有一些还不大理解,再多做两道题吧!)
加油,相信自己。四千多毫秒,比树链剖分慢多了。 注意一开始要把mx[0] 弄得很小,否则会出错。
1 #include<cstdio> 2 #include<iostream> 3 #define rep(i,j,k) for(int i = j; i <= k; i++) 4 #define maxn 30005 5 using namespace std; 6 7 int read() 8 { 9 int s = 0, t = 1; char c = getchar(); 10 while( !isdigit(c) ){ 11 if( c =='-' ) t = -1; c = getchar(); 12 } 13 while( isdigit(c) ){ 14 s = s * 10 + c - '0'; c= getchar(); 15 } 16 return s * t; 17 } 18 19 int mx[maxn], c[maxn][2], sum[maxn], w[maxn]; 20 int u[maxn], v[maxn], q[maxn], fa[maxn], n, m, top; 21 bool rev[maxn]; 22 23 bool root(int x) 24 { 25 return c[fa[x]][0] != x && c[fa[x]][1] != x; 26 } 27 28 void pushdown(int x) 29 { 30 if( rev[x] ){ 31 int l = c[x][0], r = c[x][1]; 32 rev[x] ^= 1, rev[l] ^= 1, rev[r] ^= 1; 33 swap(c[x][0],c[x][1]); 34 } 35 } 36 37 void update(int x) 38 { 39 int l = c[x][0], r = c[x][1]; 40 sum[x] = sum[l] + sum[r] + w[x]; 41 mx[x] = max(max(mx[l],mx[r]),w[x]); 42 } 43 44 void rorate(int x) 45 { 46 int y = fa[x], z = fa[y]; 47 int l = (c[y][0] == x), r = l ^ 1; 48 if( !root(y) ) c[z][y==c[z][1]] = x; 49 fa[y] = x, fa[x] = z; if( c[x][l] ) fa[c[x][l]] = y; 50 c[y][r] = c[x][l]; c[x][l] = y; 51 update(y), update(x); 52 } 53 54 void splay(int x) 55 { 56 q[++top] = x; 57 for(int i = x; !root(i); i=fa[i]){ 58 q[++top] = fa[i]; 59 } 60 while( top ) pushdown(q[top--]); 61 while( !root(x) ){ 62 int y = fa[x], z = fa[y]; 63 if( !root(y) ){ 64 if( c[y][0] == x ^ c[z][0] == y ) rorate(x); 65 else rorate(y); 66 } 67 rorate(x); 68 } 69 } 70 71 void access(int x) 72 { 73 for(int t = 0; x; t = x, x = fa[x]){ 74 splay(x), c[x][1] = t, update(x); 75 } 76 } 77 78 void makeroot(int x) 79 { 80 access(x), splay(x); rev[x] ^= 1; 81 } 82 83 void join(int x, int y) 84 { 85 makeroot(x), fa[x] = y; 86 } 87 88 void split(int x, int y) 89 { 90 makeroot(x), access(y), splay(y); 91 } 92 93 int main() 94 { 95 n = read(), mx[0] = -0x7fffffff; 96 rep(i,1,n-1){ 97 u[i] = read(), v[i] = read(); 98 } 99 rep(i,1,n){ 100 sum[i] = w[i] = mx[i] = read(); 101 } 102 rep(i,1,n-1){ 103 join(u[i],v[i]); 104 } 105 m = read(); char ch[10]; 106 rep(i,1,m){ 107 scanf("%s", ch); 108 int u = read(), v = read(); 109 if( ch[1] == 'H' ){ 110 splay(u); 111 w[u] = v; 112 update(u); 113 } 114 if( ch[1] == 'M' ){ 115 split(u,v); printf("%d\n", mx[v]); 116 } 117 if( ch[1] == 'S' ) { 118 split(u,v); printf("%d\n", sum[v]); 119 } 120 } 121 return 0; 122 }
————————————————