[bzoj3786] 星系探索

这道题搞了好几天......当然不是一直在搞,中间考了场试,改了改考试题......

这题先写的东西觉得思路太混乱,翻了翻题解之后思路清晰了一些,重构了。

题目传送门

这道题思路很清楚:用splay维护入栈出栈序。

对于子树修改的操作,splay之后,打标记。

对于换根的操作,splay之后把整个子树拿下来,再splay,最后再接到上面。

在入栈出栈序的体现就是区间的平移:1 2 3 3 2 4 4 1 --> 1 2 2 4 3 3 4 1 (此为把3的根从2换成4)。

查询操作就是查询入栈出栈序上,in[p]的前缀和。

具体写的话就比较复杂了,码量比较大。

解释代码里几个名称:

empty就是指空位置,由于0有用,所以不能用0作为空位置。

我们可以让没用到的n*2+2作为空位置的标志。

in,out入栈出栈。

fl标记是正是负,入栈处为正,出栈处为负。

sz不是指splay中的子树大小,而是子树中fl的和。

v指节点值,sum指splay中子树的v的和。

lz为懒惰标记。

注意要开long long。

  1 #include<cstdio>
  2 #define empty 2*n+2
  3 #define ll long long
  4 #define id(x) (s[f[x]][1]==x)
  5 
  6 int n,m;
  7 int hd[100005],nx[200010],to[200010],ec;
  8 int in[100005],out[100005],iv[100005];
  9 int s[200010][2],f[200010],root;
 10 ll v[200010],sum[200010],lz[200010];
 11 int fl[200010],sz[200010];
 12 int dc;
 13 
 14 void dfs(int p)
 15 {
 16     in[p]=++dc;
 17     v[dc]=sum[dc]=iv[p];
 18     sz[dc]=fl[dc]=1;
 19     for(int i=hd[p];i;i=nx[i])dfs(to[i]);
 20     out[p]=++dc;
 21     v[dc]=sum[dc]=-iv[p];
 22     sz[dc]=fl[dc]=-1;
 23 }
 24 
 25 void pushup(int p)
 26 {
 27     sum[p]=sum[s[p][0]]+sum[s[p][1]]+v[p];
 28     sz[p]=sz[s[p][0]]+sz[s[p][1]]+fl[p];
 29 }
 30 
 31 int build(int l,int r)
 32 {
 33     if(l>r)return empty;
 34     int mid=(l+r)>>1;
 35     s[mid][0]=build(l,mid-1);
 36     s[mid][1]=build(mid+1,r);
 37     if(s[mid][0]!=empty)f[s[mid][0]]=mid;
 38     if(s[mid][1]!=empty)f[s[mid][1]]=mid;
 39     pushup(mid);
 40     return mid;
 41 }
 42 
 43 void pushdown(int p)
 44 {
 45     if(!lz[p])return;
 46     if(s[p][0]!=empty)
 47     {
 48         sum[s[p][0]]+=sz[s[p][0]]*lz[p];
 49         v[s[p][0]]+=fl[s[p][0]]*lz[p];
 50         lz[s[p][0]]+=lz[p];
 51     }
 52     if(s[p][1]!=empty)
 53     {
 54         sum[s[p][1]]+=sz[s[p][1]]*lz[p];
 55         v[s[p][1]]+=fl[s[p][1]]*lz[p];
 56         lz[s[p][1]]+=lz[p];
 57     }
 58     lz[p]=0;
 59 }
 60 
 61 void rotate(int p)
 62 {
 63     int fa=f[p];
 64     int k=id(p);
 65     s[fa][k]=s[p][!k];
 66     s[p][!k]=fa;
 67     s[f[fa]][id(fa)]=p;
 68     f[p]=f[fa];
 69     f[s[fa][k]]=fa;
 70     f[fa]=p;
 71     pushup(fa);
 72     pushup(p);
 73 }
 74 
 75 void update(int p)
 76 {
 77     if(p!=root)update(f[p]);
 78     pushdown(p);
 79 }
 80 
 81 void splay(int p,int g)
 82 {
 83     update(p);
 84     while(f[p]!=g)
 85     {
 86         int fa=f[p];
 87         if(f[fa]==g)
 88         {
 89             rotate(p);
 90             break;
 91         }
 92         if(id(p)^id(fa))rotate(p);
 93         else rotate(fa);
 94         rotate(p);
 95     }
 96     if(g==empty)root=p;
 97 }
 98 
 99 int pre(int p)
100 {
101     if(s[p][0]!=empty)
102     {
103         for(p=s[p][0];s[p][1]!=empty;p=s[p][1]);
104         return p;
105     }
106     while(id(p)==0)p=f[p];
107     return f[p];
108 }
109 
110 int post(int p)
111 {
112     if(s[p][1]!=empty)
113     {
114         for(p=s[p][1];s[p][0]!=empty;p=s[p][0]);
115         return p;
116     }
117     while(id(p)==1)p=f[p];
118     return f[p];
119 }
120 
121 void quary()
122 {
123     int x;
124     scanf("%d",&x);
125     splay(post(in[x]),empty);
126     printf("%lld\n",sum[s[root][0]]);    
127 }
128 
129 void change()
130 {
131     int x,y;
132     scanf("%d%d",&x,&y);
133     splay(pre(in[x]),empty);
134     splay(post(out[x]),root);
135     int tar=s[root][1];
136     int tmp=s[tar][0];
137     s[tar][0]=empty;
138     f[tmp]=empty;
139     sz[tar]-=sz[tmp];
140     sum[tar]-=sum[tmp];
141     sz[root]-=sz[tmp];
142     sum[root]-=sum[tmp];
143     splay(in[y],empty);
144     splay(post(in[y]),root);
145     tar=s[root][1];
146     s[tar][0]=tmp;
147     f[tmp]=tar;
148     pushup(tar);
149     pushup(root);
150 }
151 
152 void flux()
153 {
154     int x,y;
155     scanf("%d%d",&x,&y);
156     splay(pre(in[x]),empty);
157     splay(post(out[x]),root);
158     int tar=s[s[root][1]][0];
159     lz[tar]+=y;
160     sum[tar]+=sz[tar]*y;
161     v[tar]+=fl[tar]*y;
162     tar=f[tar];
163     pushup(tar);
164     pushup(root);
165 }
166 
167 int main()
168 {
169     scanf("%d",&n);
170     for(int i=2;i<=n;i++)
171     {
172         int t;
173         scanf("%d",&t);
174         to[++ec]=i;
175         nx[ec]=hd[t];
176         hd[t]=ec;
177     }
178     for(int i=1;i<=n;i++)scanf("%d",&iv[i]);
179     for(int i=0;i<=2*n+1;i++)f[i]=s[i][0]=s[i][1]=empty;
180     dfs(1);
181     root=build(0,2*n+1);
182     scanf("%d",&m);
183     while(m--)
184     {
185         char op[5];
186         scanf("%s",op+1);
187         if(op[1]=='Q')quary();
188         if(op[1]=='C')change();
189         if(op[1]=='F')flux();
190     }
191     return 0;
192 }
bzoj 3786

 

posted @ 2018-09-04 19:30  cervusky  阅读(241)  评论(0编辑  收藏  举报

Contact with me