BZOJ 3786 星系探索 (splay+dfs序)
题目大意:给你一棵树,支持一下三种操作
1.获取某节点到根节点的路径上所有节点的权值和
2.更换某棵子树的父亲
3.某子树内所有节点的权值都增加一个值w
当时想到了splay维护dfs序,查完题解发现思路是对的,然后我就写了足足6个小时才A
st[x]代表入栈时间,ed[x]代表出栈时间
对于第一个操作,每个树上节点在splay中都有两个位置,分别对应入栈出栈序,然后把入栈的点权*1,出栈点权*-1,就可以避免其它子树干扰了
接着查询到根节点的路径权值和呢,splay把1~st[x]整个序列都扔到一个子树里,求一下子树权值和即可
第二个操作,可以找一下st[x]和ed[x]对应splay中节点的前驱和后继,把它们都搞到一个splay子树里,在把整棵树接到要求的父节点即可
第三个操作,和第二个操作类似,找前驱后继然后在子树打标记即可,此外,还要维护splay子树内的入栈节点数-出栈节点数来直接得到splay子树的权值和。
注意,一定要在所有能传标记的地方都传标记,不论是从下往上splay,还是从上到下找前驱or后继,而如果不在找前驱后继的过程中下传标记,上层的标记无法被传到下层,导致结果错误!就这个错误我调了2个小时!
1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 #define N 200100 5 #define il inline 6 #define ll long long 7 #define root d[0].ch[1] 8 using namespace std; 9 10 char q[10]; 11 int n,m,cte,tot; 12 int st[N],ed[N],head[N],sq[N]; 13 ll w[N]; 14 struct EDGE{int to,nxt;}edge[N]; 15 struct SPLAY{int fa,ch[2],ss,fl;ll val,sum,tag;}d[N]; 16 il int idf(int x){return d[d[x].fa].ch[0]==x?0:1;} 17 il void con(int x,int ff,int p){d[ff].ch[p]=x;d[x].fa=ff;} 18 il void pushup(int x){ 19 d[x].sum=d[d[x].ch[0]].sum+d[d[x].ch[1]].sum+d[x].val; 20 d[x].ss=d[d[x].ch[0]].ss+d[d[x].ch[1]].ss+d[x].fl; 21 } 22 il void pushdown(int x){ 23 if(!d[x].tag) return; 24 int ls=d[x].ch[0],rs=d[x].ch[1]; 25 d[ls].tag+=d[x].tag,d[rs].tag+=d[x].tag; 26 d[ls].val+=d[x].tag*(ll)d[ls].fl,d[rs].val+=d[x].tag*(ll)d[rs].fl; 27 d[ls].sum+=d[x].tag*(ll)d[ls].ss,d[rs].sum+=d[x].tag*(ll)d[rs].ss; 28 d[x].tag=0; 29 } 30 il void rot(int x){ 31 int y=d[x].fa;int ff=d[y].fa;int px=idf(x);int py=idf(y); 32 pushdown(y),pushdown(x); 33 con(d[x].ch[px^1],y,px),con(y,x,px^1),con(x,ff,py); 34 pushup(y),pushup(x); 35 } 36 il void splay(int x,int to){ 37 to=d[to].fa; 38 while(d[x].fa!=to){ 39 int y=d[x].fa; 40 if(d[y].fa==to) rot(x); 41 else if(idf(x)==idf(y)) rot(y),rot(x); 42 else rot(x),rot(x);} 43 } 44 int gc(){ 45 int rett=0,fh=1;char p=getchar(); 46 while(p<'0'||p>'9'){if(p=='-')fh=-1;p=getchar();} 47 while(p>='0'&&p<='9'){rett=(rett<<3)+(rett<<1)+p-'0';p=getchar();} 48 return rett*fh; 49 } 50 void ae(int u,int v){ 51 cte++;edge[cte].to=v; 52 edge[cte].nxt=head[u];head[u]=cte; 53 } 54 void dfs1(int u,int ff) 55 { 56 st[u]=++tot,sq[tot]=u,d[tot].val=w[u],d[tot].fl=1; 57 for(int j=head[u];j!=-1;j=edge[j].nxt){ 58 int v=edge[j].to; 59 if(v==ff) continue; 60 dfs1(v,u);} 61 ed[u]=++tot,sq[tot]=u,d[tot].val=-w[u],d[tot].fl=-1; 62 } 63 int build(int l,int r) 64 { 65 if(l>r) return 0; 66 int mid=(l+r)>>1; 67 con(build(l,mid-1),mid,0); 68 con(build(mid+1,r),mid,1); 69 pushup(mid); 70 return mid; 71 } 72 int lower(int x) 73 { 74 pushdown(x),x=d[x].ch[0]; 75 while(x){ 76 pushdown(x); 77 if(d[x].ch[1]) x=d[x].ch[1]; 78 else break;} 79 return x; 80 } 81 int upper(int x) 82 { 83 pushdown(x),x=d[x].ch[1]; 84 while(x){ 85 pushdown(x); 86 if(d[x].ch[0]) x=d[x].ch[0]; 87 else break;} 88 return x; 89 } 90 ll query(int x) 91 { 92 splay(st[0],root); 93 splay(st[x],d[root].ch[1]); 94 int lw=upper(st[x]); 95 splay(lw,d[root].ch[1]); 96 return d[d[lw].ch[0]].sum; 97 } 98 void add(int x,ll ww) 99 { 100 int trl,trr,rt; 101 splay(st[x],root); 102 splay(ed[x],d[root].ch[1]); 103 trl=lower(st[x]); 104 splay(trl,root); 105 trr=upper(ed[x]); 106 splay(trr,d[root].ch[1]); 107 rt=d[trr].ch[0]; 108 d[rt].val+=ww*(ll)d[rt].fl; 109 d[rt].sum+=ww*(ll)d[rt].ss; 110 d[rt].tag+=ww; 111 } 112 void mov(int x,int y) 113 { 114 int trl,trr,frt,rtt; 115 splay(st[x],root); 116 splay(ed[x],d[root].ch[1]); 117 trl=lower(st[x]); 118 splay(trl,root); 119 trr=upper(ed[x]); 120 splay(trr,d[root].ch[1]); 121 pushdown(trl),pushdown(trr); 122 rtt=d[trr].ch[0]; 123 d[trr].ch[0]=0,d[rtt].fa=0; 124 pushup(trr),pushup(trl); 125 126 splay(st[y],root); 127 splay(ed[y],d[root].ch[1]); 128 trl=lower(ed[y]); 129 if(trl) con(rtt,trl,1); 130 else con(rtt,ed[y],0); 131 splay(rtt,root); 132 } 133 void print(int x) 134 { 135 if(d[x].ch[0]) print(d[x].ch[0]); 136 printf("%d ",sq[x]); 137 if(d[x].ch[1]) print(d[x].ch[1]); 138 } 139 140 int main() 141 { 142 scanf("%d",&n); 143 int x,y; 144 memset(head,-1,sizeof(head)); 145 for(int i=2;i<=n;i++) 146 x=gc(),ae(x,i),ae(i,x); 147 for(int i=1;i<=n;i++) 148 w[i]=gc(); 149 st[0]=++tot,dfs1(1,-1),ed[0]=++tot; 150 root=build(1,tot); 151 scanf("%d",&m); 152 for(int i=1;i<=m;i++){ 153 scanf("%s",q); 154 if(q[0]=='Q'){ 155 x=gc(); 156 printf("%lld\n",query(x)); 157 }else if(q[0]=='F'){ 158 x=gc(),y=gc(); 159 add(x,(ll)y); 160 }else{ 161 x=gc(),y=gc(); 162 mov(x,y); 163 } 164 } 165 /*for(int i=1;i<=n;i++) 166 printf("%lld %lld %lld\n",query(i),d[st[i]].val,d[ed[i]].val);*/ 167 return 0; 168 }