[CodeChef-QTREE]Queries on tree again!

Posted skylee的OI博客

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[CodeChef-QTREE]Queries on tree again!相关的知识,希望对你有一定的参考价值。

题目大意:
  给定一个环长为奇数的带权基环树,支持以下两种操作:
    1.两点间最短路取反;
    2.两点间最短路求最大子段和。
思路:
  首先找出环,然后对每一个外向树轻重链剖分,
  用线段树维护每一个区间的和、前缀和最值、后缀和最值及子段最值。
  每次修改时,分下列两种情况讨论:
    1.两个点在同一棵外向树上,按照普通的树链剖分修改,线段树上打取反的标记。
    2.两个点再不同外向树上,先各自沿着链往上跳,然后都跳到环上的时候,可以将两个点在环中的序号减一减,对环长取模,看看哪个小。
  查询时大致和修改一样,但是合并两个区间的时候很麻烦,要注意考虑完全。
细节:
  1.找环可以在DFS的时候和树剖一起完成,也可以用并查集写,两个效率差不多。
  2.标记可以打好几次,所以不能简单地把标记赋值为true,而是每次取反。
这题代码量比较大,vjudge上除了周骏东都是10K左右。网上的题解也很少,中英文都没有找到。
一开始写挂的地方特别多,对拍对了好多次才排出所有的错。

 

  1 #include<cstdio>
  2 #include<cctype>
  3 #include<vector>
  4 inline int getint() {
  5     char ch;
  6     bool neg=false;
  7     while(!isdigit(ch=getchar())) if(ch==-) neg=true;
  8     int x=ch^0;
  9     while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^0);
 10     return neg?-x:x;
 11 }
 12 const int V=100001;
 13 struct Edge {
 14     int to,w;
 15 };
 16 std::vector<Edge> e[V];
 17 inline void add_edge(const int u,const int v,const int w) {
 18     e[u].push_back((Edge){v,w});
 19 }
 20 int par[V],size[V],son[V],cyc[V],id[V],w[V],root[V],dep[V],top[V];
 21 int cnt_cyc,cnt;
 22 bool on_cycle[V];
 23 bool dfs1(const int x,const int p) {
 24     if(par[x]||(x==1&&p!=0)) {
 25         on_cycle[x]=true;
 26         return true;
 27     } 
 28     size[x]=1;
 29     par[x]=p;
 30     bool flag=false;
 31     for(unsigned i=0;i<e[x].size();i++) {
 32         int &y=e[x][i].to;
 33         if(y==p||on_cycle[y]) continue;
 34         if(dfs1(y,x)) {
 35             par[x]=0;
 36             id[y]=++cnt;
 37             w[cnt]=e[x][i].w;
 38             if(on_cycle[x]) {
 39                 flag=true;
 40             } else {
 41                 on_cycle[x]=true;
 42             }
 43         } else {
 44             size[x]+=size[y];
 45             if(size[y]>size[son[x]]) son[x]=y;
 46         }
 47     }
 48     if(on_cycle[x]) cyc[++cnt_cyc]=x;
 49     return on_cycle[x]^flag;
 50 }
 51 int rt;
 52 void dfs2(const int x) {
 53     dep[x]=dep[par[x]]+1;
 54     top[x]=x==son[par[x]]?top[par[x]]:x;
 55     root[x]=cyc[rt];
 56     if(son[x]) {
 57         id[son[x]]=++cnt;
 58         dfs2(son[x]);
 59     }
 60     for(unsigned i=0;i<e[x].size();i++) {
 61         int &y=e[x][i].to;
 62         if(y==par[x]||on_cycle[y]) continue;
 63         if(y==son[x]) {
 64             w[id[y]]=e[x][i].w;
 65             continue;
 66         }
 67         id[y]=++cnt;
 68         w[cnt]=e[x][i].w;
 69         dfs2(y);
 70     }
 71 }
 72 void dfs3(const int x,const int p) {
 73     par[x]=p;
 74     son[x]=0;
 75     size[x]=1;
 76     for(unsigned i=0;i<e[x].size();i++) {
 77         int &y=e[x][i].to;
 78         if(y==p||on_cycle[y]) continue;
 79         dfs3(y,x);
 80         size[x]+=size[y];
 81         if(size[y]>size[son[x]]) son[x]=y;
 82     }
 83 }
 84 class SegmentTree {
 85     private:
 86         int left[V<<1],right[V<<1];
 87         long long sum[V<<1],submax[V<<1],submin[V<<1],premax[V<<1],premin[V<<1],sufmax[V<<1],sufmin[V<<1];
 88         bool neg[V<<1];
 89         int sz,newnode() {
 90             return ++sz;
 91         }
 92         void negate(long long &x) {
 93             x=-x;
 94         }
 95         void reverse(const int p) {
 96             negate(sum[p]);
 97             negate(submax[p]);
 98             negate(submin[p]);
 99             std::swap(submax[p],submin[p]);
100             negate(premax[p]);
101             negate(premin[p]);
102             std::swap(premax[p],premin[p]);
103             negate(sufmax[p]);
104             negate(sufmin[p]);
105             std::swap(sufmax[p],sufmin[p]);
106         }
107         void push_up(const int p) {
108             sum[p]=sum[left[p]]+sum[right[p]];
109             submax[p]=std::max(std::max(submax[left[p]],submax[right[p]]),sufmax[left[p]]+premax[right[p]]);
110             submin[p]=std::min(std::min(submin[left[p]],submin[right[p]]),sufmin[left[p]]+premin[right[p]]);
111             premax[p]=std::max(premax[left[p]],sum[left[p]]+premax[right[p]]);
112             premin[p]=std::min(premin[left[p]],sum[left[p]]+premin[right[p]]);
113             sufmax[p]=std::max(sufmax[right[p]],sum[right[p]]+sufmax[left[p]]);
114             sufmin[p]=std::min(sufmin[right[p]],sum[right[p]]+sufmin[left[p]]);
115         }
116         void push_down(const int p) {
117             if(!neg[p]) return;
118             reverse(left[p]);
119             reverse(right[p]);
120             neg[p]=false;
121             neg[left[p]]=!neg[left[p]];
122             neg[right[p]]=!neg[right[p]];
123         }
124     public:
125         struct Ans {
126             long long sum,pre,sub,suf;
127         };
128         int root;
129         void build(int &p,const int b,const int e) {
130             p=newnode();
131             if(b==e) {
132                 sum[p]=w[b];
133                 submax[p]=premax[p]=sufmax[p]=std::max(w[b],0);
134                 submin[p]=premin[p]=sufmin[p]=std::min(w[b],0);
135                 return;
136             }
137             int mid=(b+e)>>1;
138             build(left[p],b,mid);
139             build(right[p],mid+1,e);
140             push_up(p);
141         }
142         void modify(const int p,const int b,const int e,const int l,const int r) {
143             if((b==l)&&(e==r)) {
144                 reverse(p);
145                 neg[p]=!neg[p];
146                 return;
147             }
148             push_down(p);
149             int mid=(b+e)>>1;
150             if(l<=mid) modify(left[p],b,mid,l,std::min(mid,r));
151             if(r>mid) modify(right[p],mid+1,e,std::max(mid+1,l),r);
152             push_up(p);
153         }
154         Ans query(const int p,const int b,const int e,const int l,const int r) {
155             if((b==l)&&(e==r)) {
156                 return (Ans){sum[p],premax[p],submax[p],sufmax[p]};
157             }
158             push_down(p);
159             int mid=(b+e)>>1;
160             long long leftsum=0,leftpre=0,leftsub=0,leftsuf=0,rightsum=0,rightpre=0,rightsub=0,rightsuf=0;
161             if(l<=mid) {
162                 Ans tmp=query(left[p],b,mid,l,std::min(mid,r));
163                 leftsum=tmp.sum;
164                 leftpre=tmp.pre;
165                 leftsub=tmp.sub;
166                 leftsuf=tmp.suf;
167             }
168             if(r>mid) {
169                 Ans tmp=query(right[p],mid+1,e,std::max(mid+1,l),r);
170                 rightsum=tmp.sum;
171                 rightpre=tmp.pre;
172                 rightsub=tmp.sub;
173                 rightsuf=tmp.suf;
174             }
175             long long sum,pre,sub,suf;
176             sum=leftsum+rightsum;
177             pre=std::max(leftpre,leftsum+rightpre);
178             sub=std::max(std::max(leftsub,rightsub),leftsuf+rightpre);
179             suf=std::max(rightsuf,rightsum+leftsuf);
180             return (Ans){sum,pre,sub,suf};
181         }
182 };
183 SegmentTree t;
184 int n;
185 inline void modify(int x,int y) {
186     if(root[x]!=root[y]) {
187         while(top[x]!=root[x]) {
188             t.modify(t.root,1,n,id[top[x]],id[x]);
189             x=par[top[x]];
190         }
191         if(x!=top[x]) {
192             t.modify(t.root,1,n,id[son[top[x]]],id[x]);
193             x=top[x];
194         }
195         while(top[y]!=root[y]) {
196             t.modify(t.root,1,n,id[top[y]],id[y]);
197             y=par[top[y]];
198         }
199         if(y!=top[y]) {
200             t.modify(t.root,1,n,id[son[top[y]]],id[y]);
201             y=top[y];
202         }
203     } else {
204         while(top[x]!=top[y]) {
205             if(dep[top[x]]<dep[top[y]]) std::swap(x,y);
206             t.modify(t.root,1,n,id[top[x]],id[x]);
207             x=par[top[x]];
208         }
209         if(x!=y) {
210             if(dep[x]<dep[y]) std::swap(x,y);
211             t.modify(t.root,1,n,id[son[y]],id[x]);
212         }
213         return;
214     }
215     if((id[y]-id[x]+cnt_cyc)%cnt_cyc>(id[x]-id[y]+cnt_cyc)%cnt_cyc) std::swap(x,y);
216     if(id[x]<id[y]) {
217         t.modify(t.root,1,n,id[x],id[y]-1);
218     } else {
219         t.modify(t.root,1,n,id[x],cnt_cyc);
220         if(id[y]!=1) t.modify(t.root,1,n,1,id[y]-1);
221     }
222 }
223 inline long long query(int x,int y) {
224     long long lastsum=0,lastpre=0,lastsub=0,lastsuf=0,nextsum=0,nextpre=0,nextsub=0,nextsuf=0;
225     long long ans=0;
226     if(root[x]!=root[y]) {
227         while(top[x]!=root[x]) {
228             SegmentTree::Ans tmp=t.query(t.root,1,n,id[top[x]],id[x]);
229             lastsub=std::max(std::max(lastsub,tmp.sub),lastpre+tmp.suf);
230             lastpre=std::max(tmp.pre,lastpre+tmp.sum);
231             lastsuf=std::max(lastsuf,lastsum+tmp.suf);
232             lastsum+=tmp.sum;
233             ans=std::max(ans,lastsub);
234             x=par[top[x]];
235         }
236         if(x!=top[x]) {
237             SegmentTree::Ans tmp=t.query(t.root,1,n,id[son[top[x]]],id[x]);
238             lastsub=std::max(std::max(lastsub,tmp.sub),lastpre+tmp.suf);
239             lastpre=std::max(tmp.pre,lastpre+tmp.sum);
240             lastsuf=std::max(lastsuf,lastsum+tmp.suf);
241             lastsum+=tmp.sum;
242             ans=std::max(ans,lastsub);
243             x=top[x];
244         }
245         while(top[y]!=root[y]) {
246             SegmentTree::Ans tmp=t.query(t.root,1,n,id[top[y]],id[y]);
247             nextsub=std::max(std::max(nextsub,tmp.sub),nextpre+tmp.suf);
248             nextpre=std::max(tmp.pre,nextpre+tmp.sum);
249             nextsuf=std::max(nextsuf,nextsum+tmp.suf);
250             nextsum+=tmp.sum;
251             ans=std::max(ans,nextsub);
252             y=par[top[y]];
253         }
254          if(y!=top[y]) {
255             SegmentTree::Ans tmp=t.query(t.root,1,n,id[son[top[y]]],id[y]);
256             nextsub=std::max(std::max(nextsub,tmp.sub),nextpre+tmp.suf);
257             nextpre=std::max(tmp.pre,nextpre+tmp.sum);
258             nextsuf=std::max(nextsuf,nextsum+tmp.suf);
259             nextsum+=tmp.sum;
260             ans=std::max(ans,nextsub);
261             y=top[y];
262         }
263     } else {
264         while(top[x]!=top[y]) {
265             if(dep[top[x]]<dep[top[y]]) {
266                 std::swap(x,y);
267                 std::swap(lastsum,nextsum);
268                 std::swap(lastsub,nextsub);
269                 std::swap(lastpre,nextpre);
270                 std::swap(lastsuf,nextsuf);
271             }
272             SegmentTree::Ans tmp=t.query(t.root,1,n,id[top[x]],id[x]);
273             lastsub=std::max(std::max(lastsub,tmp.sub),lastpre+tmp.suf);
274             lastpre=std::max(tmp.pre,lastpre+tmp.sum);
275             lastsuf=std::max(lastsuf,lastsum+tmp.suf);
276             lastsum+=tmp.sum;
277             ans=std::max(ans,lastsub);
278             x=par[top[x]];
279         }
280         if(x!=y) {
281             if(dep[x]<dep[y]) {
282                 std::swap(x,y);
283                 std::swap(lastsum,nextsum);
284                 std::swap(lastsub,nextsub);
285                 std::swap(lastpre,nextpre);
286                 std::swap(lastsuf,nextsuf);
287             }
288             SegmentTree::Ans tmp=t.query(t.root,1,n,id[son[y]],id[x]);
289             lastsub=std::max(std::max(lastsub,tmp.sub),lastpre+tmp.suf);
290             lastpre=std::max(tmp.pre,lastpre+tmp.sum);
291             lastsuf=std::max(lastsuf,lastsum+tmp.suf);
292             lastsum+=tmp.sum;
293         }
294         ans=std::max(ans,std::max(lastsub,lastpre+nextpre));
295         return ans;
296     }
297     if((id[y]-id[x]+cnt_cyc)%cnt_cyc>(id[x]-id[y]+cnt_cyc)%cnt_cyc) {
298         std::swap(x,y);
299         std::swap(lastsum,nextsum);
300         std::swap(lastsub,nextsub);
301         std::swap(lastpre,nextpre);
302         std::swap(lastsuf,nextsuf);
303     }
304     SegmentTree::Ans tmp;
305     if(id[x]<id[y]) {
306         tmp=t.query(t.root,1,n,id[x],id[y]-1);
307     } else {
308         SegmentTree::Ans tmp1,tmp2;
309         tmp1=t.query(t.root,1,n,id[x],cnt_cyc);
310         if(id[y]!=1) tmp2=t.query(t.root,1,n,1,id[y]-1);
311         if(id[y]!=1) {
312             tmp.sum=tmp1.sum+tmp2.sum;
313             tmp.sub=std::max(std::max(tmp1.sub,tmp2.sub),tmp1.suf+tmp2.pre);
314             tmp.pre=std::max(tmp1.pre,tmp1.sum+tmp2.pre);
315             tmp.suf=std::max(tmp2.suf,tmp2.sum+tmp1.suf);
316         } else {
317             tmp=tmp1;
318         }
319     }
320     ans=std::max(ans,tmp.sub);
321     ans=std::max(ans,lastpre+tmp.pre);
322     ans=std::max(ans,nextpre+tmp.suf);
323     ans=std::max(ans,lastpre+nextpre+tmp.sum);
324     return ans;
325 }
326 int main() {
327     n=getint();
328     for(int i=1;i<=n;i++) {
329         int u=getint(),v=getint(),w=getint();
330         add_edge(u,v,w);
331         add_edge(v,u,w);
332     }
333     dfs1(1,0);
334     for(rt=1;rt<=cnt_cyc;rt++) {
335         if(rt==cnt_cyc) dfs3(cyc[rt],0);
336         dfs2(cyc[rt]);
337     }
338     t.build(t.root,1,n);
339     for(int m=getint();m;m--) {
340         char op[2];
341         scanf("%1s",op);
342         switch(op[0]) {
343             case f: {
344                 int x=getint(),y=getint();
345                 modify(x,y);
346                 break;
347             }
348             case ?: {
349                 int x=getint(),y=getint();
350                 printf("%lld\n",query(x,y));
351                 break;
352             }
353         }
354     }
355     return 0;
356 }

 附数据生成器:

技术分享
 1 #include<ctime>
 2 #include<vector>
 3 #include<cstdio>
 4 #include<cstdlib>
 5 const int V=100001;
 6 std::vector<int> e[V];
 7 inline void add_edge(const int u,const int v) {
 8     e[u].push_back(v);
 9 }
10 int par[V],dep[V],top[V],son[V],size[V];
11 void dfs1(const int x) {
12     size[x]=1;
13     dep[x]=dep[par[x]]+1;
14     for(unsigned i=0;i<e[x].size();i++) {
15         int &y=e[x][i];
16         dfs1(y);
17         size[x]+=size[y];
18         if(size[y]>size[son[x]]) son[x]=y;
19     }
20 }
21 void dfs2(const int x) {
22     top[x]=x==son[par[x]]?top[par[x]]:x;
23     for(unsigned i=0;i<e[x].size();i++) {
24         int &y=e[x][i];
25         dfs2(y);
26     }
27 }
28 inline int get_lca(int x,int y) {
29     while(top[x]!=top[y]) {
30         if(dep[top[x]]<dep[top[y]]) std::swap(x,y);
31         x=par[top[x]];
32     }
33     if(dep[x]<dep[y]) std::swap(x,y);
34     return y;
35 }
36 int main() {
37     srand(time(NULL));
38     int n=100000,m=100000,w=20001;
39     printf("%d\n",n);
40     for(int i=2;i<=n;i++) {
41         printf("%d %d %d\n",par[i]=rand()%(i-1)+1,i,rand()%w-w/2);
42         add_edge(par[i],i);
43     }
44     dfs1(1);
45     dfs2(1);
46     for(int i=1;i<n;i++) {
47         if(i!=par[n]) {
48             int lca=get_lca(i,n);
49             if((dep[i]+dep[n]-dep[lca]*2)&1) continue;
50             printf("%d %d %d\n",i,n,rand()%w-w/2);
51             break;
52         }
53     }
54     printf("%d\n",m);
55     for(int i=1;i<=m;i++) {
56         int op=rand()%2;
57         if(op) {
58             int y=rand()%(n-2)+2;
59             int x=rand()%(y-1)+1;
60             printf("? %d %d\n",x,y);
61         } else {
62             int y=rand()%(n-2)+2;
63             int x=rand()%(y-1)+1;
64             printf("f %d %d\n",x,y);
65         }
66     }
67     return 0;
68 }
View Code

 

以上是关于[CodeChef-QTREE]Queries on tree again!的主要内容,如果未能解决你的问题,请参考以下文章

Array Queries CodeForces - 797E

HDU - 5412 CRB and Queries (整体二分)

线段树 SP1716 GSS3 - Can you answer these queries III

CF 375D. Tree and Queries莫队

lightoj-1082 - Array Queries

LA 5031 Graph and Queries —— Treap名次树