SPOJ QTREE 系列解题报告

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SPOJ QTREE 系列解题报告相关的知识,希望对你有一定的参考价值。

题目一 : SPOJ 375 Query On a Tree

http://www.spoj.com/problems/QTREE/

给一个树,求a,b路径上最大边权,或者修改a,b边权为t。

技术分享
  1 #include <cstdio>
  2 #include <iostream>
  3 #include <cstring>
  4 #include <cstdlib>
  5 #include <algorithm>
  6 
  7 using namespace std;
  8 const int maxn = 200000 + 5;
  9 
 10 int N,pos=0;
 11 char ss[50];
 12 
 13 struct SegmentTree{
 14     int l,r,flag;
 15     int maxv,minv;
 16 }Node[maxn * 10];
 17 
 18 int e[maxn][4];
 19 int size[maxn],dep[maxn],top[maxn],son[maxn];
 20 int fa[maxn],Segnum[maxn],Treenum[maxn];
 21 
 22 int tot = 0;
 23 int first[maxn],next[maxn*2];
 24 int u[maxn*2],v[maxn*2];
 25 
 26 void clear();
 27 void change(int&,int&);
 28 void Add(int,int);
 29 void dfs_1(int,int,int);
 30 void dfs_2(int,int);
 31 void build(int,int,int);
 32 void update(int,int,int,int);
 33 int query(int,int,int);
 34 int find_max(int,int);
 35 void rever(int,int,int);
 36 void get_rever(int,int);
 37 void pushdown(int);
 38 void pushup(int);
 39 
 40 int main(){
 41     int tcase;
 42     scanf("%d",&tcase);
 43     while(tcase --){
 44         clear();
 45         int x,y,z;
 46         scanf("%d",&N);
 47         for(int i = 1;i < N;++ i){
 48             scanf("%d%d%d",&e[i][0],&e[i][1],&e[i][2]);
 49             Add(e[i][0],e[i][1]);
 50             Add(e[i][1],e[i][0]);
 51         }    
 52         
 53         dfs_1(1,0,1);
 54         dfs_2(1,1);
 55         build(1,1,N);    
 56         for(int i = 1;i < N;++ i){
 57             if(dep[e[i][0]] > dep[e[i][1]])
 58                 swap(e[i][0],e[i][1]);
 59             update(1,Segnum[e[i][1]],Segnum[e[i][1]],e[i][2]);    
 60         }
 61         while(1){
 62             scanf("%s",ss);
 63             if(ss[0] == D)
 64                 break;
 65             scanf("%d%d",&x,&y);
 66             if(ss[0] == C){
 67                 update(1,Segnum[e[x][1]],Segnum[e[x][1]],y);
 68             }
 69             else if(ss[0] == Q){
 70                 printf("%d\n",find_max(x,y));
 71             }
 72             else if(ss[0] == N){
 73                 get_rever(x,y);
 74             }
 75         }
 76     } 
 77     return 0;
 78 }
 79 
 80 void clear(){
 81     pos = 0;tot = 0;
 82     memset(son,0,sizeof son);
 83     memset(first,0,sizeof first);
 84 }
 85 void Add(int s,int t){
 86     ++ tot;
 87     u[tot] = s;v[tot] = t;
 88     next[tot] = first[u[tot]];
 89     first[u[tot]] = tot;
 90 }
 91 void dfs_1(int now,int f,int depth){
 92     size[now] = 1;
 93     fa[now] = f;
 94     dep[now] = depth;
 95     
 96     for(int i = first[now];i;i = next[i]){
 97         if(v[i] != f){
 98             dfs_1(v[i],now,depth + 1);
 99             size[now] += size[v[i]];
100             if(!son[now] || size[v[i]] > size[son[now]])
101                 son[now] = v[i];
102         }
103     }
104     return;
105 }
106 
107 void dfs_2(int now,int ances){
108     top[now] = ances;
109     Segnum[now] = ++ pos;
110     Treenum[Segnum[now]] = now;
111     
112     if(!son[now])return;
113     dfs_2(son[now],ances);
114     
115     for(int i = first[now];i;i = next[i]){
116         if(v[i] != son[now] && v[i] != fa[now]){
117             dfs_2(v[i],v[i]);
118         }
119     }
120     return;
121 }
122 
123 void build(int o,int l,int r){
124     Node[o].l = l;
125     Node[o].r = r;
126     Node[o].minv = Node[o].maxv = 0;
127     Node[o].flag = 0;
128     if(l == r)
129         return;
130     int Mid = (l + r) >> 1;
131     build(o<<1,l,Mid);
132     build(o<<1|1,Mid+1,r);
133 }
134 
135 void update(int o,int l,int r,int v){
136     if(Node[o].l == l && Node[o].r == r){
137         Node[o].minv = Node[o].maxv = v;
138         Node[o].flag = 0;
139         return;
140     }
141     int Mid = (Node[o].l + Node[o].r) >> 1;
142     pushdown(o);
143     if(r <= Mid)
144         update(o<<1,l,r,v);
145     else if(l > Mid)
146         update(o<<1|1,l,r,v);
147     pushup(o);
148 }
149 void pushdown(int o){
150     if(Node[o].l == Node[o].r)
151         return;
152     int lc = o << 1,rc = o << 1 | 1;
153     if(Node[o].flag){
154         Node[o].flag = 0;
155         Node[lc].flag ^= 1;
156         Node[rc].flag ^= 1;
157         change(Node[rc].minv,Node[rc].maxv);
158         change(Node[lc].maxv,Node[lc].minv);
159     }
160 }
161 void pushup(int o){
162     int lc = o << 1,rc = o << 1 | 1;
163     Node[o].maxv = max(Node[lc].maxv,Node[rc].maxv);
164     Node[o].minv = min(Node[lc].minv,Node[rc].minv);
165 }
166 
167 int query(int o,int l,int r){
168     if(Node[o].l == l && Node[o].r == r){
169         return Node[o].maxv;
170     }
171     int Mid = (Node[o].l + Node[o].r) >> 1;
172     pushdown(o);
173     if(r <= Mid)
174         return query(o<<1,l,r);
175     else if(l > Mid)
176         return query(o<<1|1,l,r);
177     else
178         return max(query(o<<1,l,Mid),query(o<<1|1,Mid+1,r));
179     pushup(o);
180 }
181 void rever(int o,int l,int r){
182     if(Node[o].l == l && Node[o].r == r){
183         change(Node[o].maxv,Node[o].minv);
184         Node[o].flag ^= 1;
185         return;
186     }
187     int Mid = (Node[o].l + Node[o].r) >> 1;
188     pushdown(o);
189     if(r <= Mid)
190         rever(o<<1,l,r);
191     else if(l > Mid)
192         rever(o<<1|1,l,r);
193     else{
194         rever(o<<1,l,Mid);
195         rever(o<<1|1,Mid+1,r);
196     }
197     pushup(o);
198 }
199 int find_max(int x,int y){
200     int f1 = top[x],f2 = top[y];
201     int ret = -100000;
202     
203     while(f1 != f2){
204         if(dep[f1] < dep[f2]){
205             swap(f1,f2);
206             swap(x,y);
207         }
208         ret = max(ret,query(1,Segnum[f1],Segnum[x]));
209         x = fa[f1];f1 = top[x];
210     }
211     
212     if(x == y)return ret;
213     if(dep[x] < dep[y]){
214         ret = max(ret,query(1,Segnum[son[x]],Segnum[y]));
215     }
216     else{
217         ret = max(ret,query(1,Segnum[son[y]],Segnum[x]));
218     }
219     
220     return ret;
221 }
222 
223 void get_rever(int x,int y){
224     int f1 = top[x],f2 = top[y];
225     
226     while(f1 != f2){
227         if(dep[f1] < dep[f2]){
228             swap(f1,f2);
229             swap(x,y);
230         }
231         rever(1,Segnum[f1],Segnum[x]);
232         x = fa[f1];f1 = top[x];
233     }
234     if(x == y)return;//如果是针对边的操作, 这个东西不能少。。 
235     if(dep[x] < dep[y]){
236         rever(1,Segnum[son[x]],Segnum[y]);//如果是边权,注意这里的写法。要下放。 
237     }
238     else{
239         rever(1,Segnum[son[y]],Segnum[x]);
240     }
241     return;
242 }
243 
244 void change(int &a,int &b){
245     int tp1 = a,tp2 = b;
246     a = -tp2;b = -tp1;
247     return;
248 }
树链剖分

 

以上是关于SPOJ QTREE 系列解题报告的主要内容,如果未能解决你的问题,请参考以下文章

SPOJ Qtree系列 2/7

SPOJ GSS系列解题报告

[SPOJ375]QTREE

SPOJ QTREE 树链剖分

SPOJ QTREE Query on a tree

SPOJ QTREE Query on a tree ——树链剖分 线段树