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 }

树链剖分

时间: 2024-10-17 12:52:06

SPOJ QTREE 系列解题报告的相关文章

SPOJ GSS系列 解题报告

这个系列总共有7道题,目前只做了3道,gss2比较难,gss4是暴力修改,树状数组维护,还没写,gss6和gss7还不在能力范围内. SPOJ_1043 GSS1 题意:给定长度不超过5万的序列,M次查询(貌似没给大小?..),查询所给区间内的最大子段和. 做法:线段树.维护区间和sum,区间可以得到的最大值smax,从区间最左边开始的最大和lmax和右边开始的rmax,然后就可以了.具体更新还是看代码吧.比较巧妙的在于,把query函数的类型设为线段树的节点类型,这样就可以把它的子区间用upd

SPOJ GSS系列解题报告

众所周知,\(GSS\)是用来练习线段树的一个非常好的系列. 依稀记得\(8\)月初还在\(qbxt\)时,某钟姓神仙说过 :"大家可以把\(GSS\)系列写一下,大概够大家写一个月了."虽然我很不想承认,但他确实说中了\(--\)虽然中间夹有做各种杂题和一些模拟赛\(--\) 题解 GSS 1 \(GSS\)系列最简单的一道题,也算是后面题目的一个基础. 给定一个序列,维护区间最大子段和. 我们维护这样几个东西\(:lsum, rsum, maxsum, maxval.\) 分别表示

SPOJ QTREE系列 树上分治问题。

375.Query on a tree  [QTREE] 有两个操作: (1)修改第i条边的边权 (2)询问a到b路径上的边权最大值. 树链剖分入门题.树链剖分+线段树维护最大值.修改/查询均为O(log^2). 很懒,没有写. 913.Query on a tree II [QTREE2] 有两个操作: (1)询问a到b的距离. (2)询问a到b路径上的第k个点. 很容易想到倍增LCA. 路径上的第k个点,要么是a的第k个父亲,要么是b的第k'个父亲,同样可以倍增实现. 询问都是O(logn)

小Z 系列 解题报告

在你谷刷题时偶然发现有这么一个系列,大概\(15\)道题目左右. 而且蒟蒻发现,这个系列的出题人基本上全是LittleZ大佬OrzOrz. 于是心血来潮,想把这个系列全部写完,然后便有了本文. \(P.s.:\)按蒟蒻自己的做题顺序排列,不一定代表难易. \(1.\)小Z的矩阵 因为题目中给出的特征函数\(G(A)\)是对\(2\)取模后的结果,所以很容易就可以发现除对角线以外所有元素对答案的贡献均为\(0\),所以第一步单累计对角线贡献即可. 然后我们发现每翻转一行一列对答案无影响,即刚好翻转

Spring-2-H Array Diversity(SPOJ AMR11H)解题报告及测试数据

Array Diversity Time Limit:404MS     Memory Limit:0KB     64bit IO Format:%lld & %llu Description Here we go! Let's define the diversity of a list of numbers to be the difference between the largest and smallest number in the list. For example, the d

Spring-2-J Goblin Wars(SPOJ AMR11J)解题报告及测试数据

Goblin Wars Time Limit:432MS     Memory Limit:0KB     64bit IO Format:%lld & %llu Description The wizards and witches of Hogwarts School of Witchcraft found Prof. Binn's History of Magic lesson to be no less boring than you found your own history cla

Spring-2-A Magic Grid(SPOJ AMR11A)解题报告及测试数据

Magic Grid Time Limit:336MS     Memory Limit:0KB     64bit IO Format:%lld & %llu Description Thanks a lot for helping Harry Potter in finding the Sorcerer's Stone of Immortality in October. Did we not tell you that it was just an online game ? uhhh!

Spring-2-B Save the Students(SPOJ AMR11B)解题报告及测试数据

Save the Students Time Limit:134MS     Memory Limit:0KB     64bit IO Format:%lld & %llu Description Hogwarts is under attack by the Dark Lord, He-Who-Must-Not-Be-Named. To protect the students, Harry Potter must cast protective spells so that those w

排列组合(permutation)系列解题报告

本文讲解4道关于permutation的题目: 1. Permutation:输出permutation--基础递归 2. Permutation Sequence: 输出字典序排列的第k个permutation--推理3. Next Permutation:给定一个permutation中的序列,求字典序它的下一个permutation是什么--逻辑推理4. Permutation II:和第一题有细微的差别: 对于一个可能有重复元素的数组输出所有permutation--有条件dfs