Tree
Time Limit: 5000MS   Memory Limit: 131072K
Total Submissions: 12247   Accepted: 3151

Description

You are given a tree with N nodes. The tree’s nodes are numbered 1 through N and its edges are numbered 1 through N − 1. Each edge is associated with a weight. Then you are to execute a series of instructions on the tree. The instructions can be one of the following forms:

CHANGE i v Change the weight of the ith edge to v
NEGATE a b Negate the weight of every edge on the path from a to b
QUERY a b Find the maximum weight of edges on the path from a to b

Input

The input contains multiple test cases. The first line of input contains an integer t (t ≤ 20), the number of test cases. Then follow the test cases.

Each test case is preceded by an empty line. The first nonempty line of its contains N (N ≤ 10,000). The next N − 1 lines each contains three integers ab and c, describing an edge connecting nodes a and b with weight c. The edges are numbered in the order they appear in the input. Below them are the instructions, each sticking to the specification above. A lines with the word “DONE” ends the test case.

Output

For each “QUERY” instruction, output the result on a separate line.

Sample Input

13
1 2 1
2 3 2
QUERY 1 2
CHANGE 1 3
QUERY 1 2
DONE

Sample Output

1
3

Source

POJ Monthly--2007.06.03, Lei, Tao

题意就是: 有T组数据 ,给你n个点的树,有三种操作:

1.CHANGE i v :将第i条边的值改为v

2.NEGATE a b :将a点到b点路径上的边权取反

3.QUERY a b :查询a点到b点路径上最大的边权值,

由于有取反操作,记录最大和最小值 然后取反并交换就可以,用线段树来维护,真香警告。。。

代码:

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<algorithm>
  5 #include<bitset>
  6 #include<cassert>
  7 #include<cctype>
  8 #include<cmath>
  9 #include<cstdlib>
 10 #include<ctime>
 11 #include<deque>
 12 #include<iomanip>
 13 #include<list>
 14 #include<map>
 15 #include<queue>
 16 #include<set>
 17 #include<stack>
 18 #include<vector>
 19 using namespace std;
 20 typedef long long ll;
 21
 22 const double PI=acos(-1.0);
 23 const double eps=1e-6;
 24 const ll mod=1e9+7;
 25 const int inf=0x3f3f3f3f;
 26 const int maxn=1e4+10;
 27 const int maxm=100+10;
 28 #define ios ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
 29 #define lson l,m,rt<<1
 30 #define rson m+1,r,rt<<1|1
 31
 32 int head[maxn],cnt,num,n;
 33
 34 struct Edge{
 35     int to,next;
 36 }edge[maxn<<1];
 37
 38 void add(int u,int v)//存图(树)
 39 {
 40     edge[cnt].to=v;
 41     edge[cnt].next=head[u];
 42     head[u]=cnt++;
 43 }
 44
 45 int val[maxn],siz[maxn],dep[maxn],son[maxn];
 46 int top[maxn],tid[maxn],pos[maxn],fa[maxn];
 47
 48 void init()//初始化
 49 {
 50     memset(head,-1,sizeof(head));
 51     memset(son,-1,sizeof(son));
 52     cnt=num=0;
 53 }
 54
 55 ///树链剖分部分
 56 void dfs1(int u,int father)//第一遍dfs,可以得到当前节点的父亲节点,当前节点的深度,当前节点的重儿子
 57 {
 58     //更新dep,fa,siz数组
 59     siz[u]=1;//保存以u为根的子树节点个数
 60     fa[u]=father;//保存爸爸
 61     dep[u]=dep[father]+1;//记录深度
 62     for(int i=head[u];~i;i=edge[i].next){//遍历所有和当前节点连接的节点
 63         int v=edge[i].to;
 64         if(v!=father){//如果连接的是当前节点的父亲节点,则不处理
 65             dfs1(v,u);
 66             siz[u]+=siz[v];//直接子树节点相加,当前节点的size加上子节点的size
 67             if(son[u]==-1||siz[v]>siz[son[u]])//如果没有设置过重节点son或者子节点v的size大于之前记录的重节点son,进行更新
 68                 son[u]=v;//保存重儿子
 69         }
 70     }
 71 }
 72
 73 void dfs2(int u,int tp)//将各个重节点连接成重链,轻节点连接成轻链,并且将重链(区间)用数据结构(一般是树状数组或者线段树)来维护,并且为每个节点进行编号,其实就是dfs在执行时的顺序(tid数组),以及当前节点所在链的起点(top数组)还有当前节点在树中的位置(pos)                                                                                                                                                                                                                                                                                                                                                          )
 74 {
 75     top[u]=tp;//保存当前节点所在的链的顶端节点,当前节点的起点
 76     tid[u]=++num;//保存树中每个节点剖分以后的新编号(dfs的执行顺序)
 77     pos[tid[u]]=u;//保存当前节点在树中的位置,设置dfs序号对应成当前节点
 78     if(son[u]==-1) return ;//如果当前节点没有处在重链上,则不处理
 79     dfs2(son[u],tp);//将这条重链上的所有节点都设置成起始的重节点
 80     for(int i=head[u];~i;i=edge[i].next){//遍历所有和当前节点连接的节点
 81         int v=edge[i].to;//如果连接节点不是当前节点的重节点并且也不是u的父节点,则将其的top设置成自己,进一步递归
 82         if(v!=son[u]&&v!=fa[u])
 83             dfs2(v,v);
 84     }
 85 }
 86
 87 int lazy[maxn<<2],Max[maxn<<2],Min[maxn<<2];
 88
 89 //线段树部分
 90 void Swap(int &x,int &y){int t=x;x=-y;y=-t;}
 91
 92 void pushup(int rt)
 93 {
 94     Max[rt]=max(Max[rt<<1],Max[rt<<1|1]);
 95     Min[rt]=min(Min[rt<<1],Min[rt<<1|1]);
 96 }
 97
 98 void pushdown(int rt)
 99 {
100     if(lazy[rt]){
101         lazy[rt<<1]+=lazy[rt];
102         lazy[rt<<1|1]+=lazy[rt];
103         if(lazy[rt]&1){ //两个子区间是否取反依靠当前区间的懒惰标记判断,判断奇偶
104             Swap(Max[rt<<1],Min[rt<<1]);
105             Swap(Max[rt<<1|1],Min[rt<<1|1]);
106         }
107         lazy[rt]=0;
108     }
109 }
110
111 void build(int l,int r,int rt)
112 {
113     lazy[rt]=0;
114     if(l==r){
115         Max[rt]=Min[rt]=0;
116         return ;
117     }
118
119     int m=(l+r)>>1;
120     build(lson);
121     build(rson);
122     pushup(rt);
123 }
124
125 void update(int pos,int val,int l,int r,int rt)
126 {
127     if(l==r&&l==pos){
128         Max[rt]=val;Min[rt]=val;lazy[rt]=0;
129         return ;
130     }
131
132     pushdown(rt);
133     int m=(l+r)>>1;
134     if(pos<=m) update(pos,val,lson);
135     else       update(pos,val,rson);
136     pushup(rt);
137 }
138
139 void Negate(int L,int R,int l,int r,int rt)//Negate是int tmp=Max,Max=-Min,Min=-tmp
140 {
141     if(L<=l&&r<=R){
142         lazy[rt]++;
143         Swap(Max[rt],Min[rt]);//这里要马上取反
144         return ;
145     }
146
147     pushdown(rt);
148     int m=(l+r)>>1;
149     if(L<=m) Negate(L,R,lson);
150     if(R> m) Negate(L,R,rson);
151     pushup(rt);
152 }
153
154 int query(int L,int R,int l,int r,int rt)
155 {
156     if(L<=l&&r<=R){
157         return Max[rt];
158     }
159
160     pushdown(rt);
161     int ret=-inf;
162     int m=(l+r)>>1;
163     if(L<=m) ret=max(ret,query(L,R,lson));
164     if(R> m) ret=max(ret,query(L,R,rson));
165     pushup(rt);
166     return ret;
167 }
168
169 int get_max(int u,int v)
170 {
171     int ans=-1<<30;
172     while(top[u]!=top[v]){
173         if(dep[top[u]]<dep[top[v]]) swap(u,v);
174         ans=max(ans,query(tid[top[u]],tid[u],1,n,1));
175         u=fa[top[u]];
176     }
177
178     if(dep[v]<dep[u]) swap(u,v);
179     ans=max(ans,query(tid[son[u]],tid[v],1,n,1));//这里写捞了,tid[son[u]],写成tid[u],wa了好几天。。。
180     printf("%d\n",ans);
181 }
182
183 void change(int u,int v)
184 {
185     while(top[u]!=top[v]){
186         if(dep[top[u]]<dep[top[v]]) swap(u,v);
187         Negate(tid[top[u]],tid[u],1,n,1);
188         u=fa[top[u]];
189     }
190
191     if(u==v) return ;
192     if(dep[v]<dep[u]) swap(u,v);
193     Negate(tid[son[u]],tid[v],1,n,1);
194 }
195
196 struct eg{
197     int u,v,val;
198 }eg[maxn];
199
200 int main()
201 {
202     int t;
203     scanf("%d",&t);
204     while(t--){
205         scanf("%d",&n);
206         init();
207         for(int i=1;i<n;i++){
208             scanf("%d%d%d",&eg[i].u,&eg[i].v,&eg[i].val);
209             add(eg[i].u,eg[i].v);//加边
210             add(eg[i].v,eg[i].u);//加边
211         }
212         dfs1(1,0);//第一遍dfs
213         dfs2(1,1);//第二遍dfs
214         build(1,n,1);
215         for(int i=1;i<n;i++){
216             if(dep[eg[i].u]<dep[eg[i].v]) swap(eg[i].u,eg[i].v);
217             update(tid[eg[i].u],eg[i].val,1,n,1);
218         }
219         int a,b;
220         char op[10];
221         while(scanf("%s",op)&&op[0]!='D'){
222             scanf("%d%d",&a,&b);
223             if(op[0]=='Q'){
224                 get_max(a,b);
225             }
226             if(op[0]=='C'){
227                 update(tid[eg[a].u],b,1,n,1);
228             }
229             if(op[0]=='N'){
230                 change(a,b);
231             }
232         }
233     }
234 }

哈哈哈哈,加油加油。

转载于:https://www.cnblogs.com/ZERO-/p/9670796.html

POJ 3237.Tree -树链剖分(边权)(边值更新、路径边权最值、区间标记)贴个板子备忘...相关推荐

  1. POJ 3237 Tree (树链剖分 路径剖分 线段树的lazy标记)

    题目链接:http://poj.org/problem?id=3237 一棵有边权的树,有3种操作. 树链剖分+线段树lazy标记.lazy为0表示没更新区间或者区间更新了2的倍数次,1表示为更新,每 ...

  2. CodeForces - 343D Water Tree(树链剖分+线段树)

    题目链接: 题目大意:给出一棵由n个点组成的树,初始时每个点的权值为0,接下来有m个操作,每个操作分为以下三种: 1 x:将包括节点x在内的所有子孙节点的权值都改为1 2 x:将包括节点x在内的所有父 ...

  3. SPOJ - QTREE Query on a tree(树链剖分+线段树)

    题目链接:点击查看 题目大意:给出一棵由n个点组成的树,再给出数个操作,每次操作分为下列几种类型: QUERY x y:询问点x-点y这条路径上的所有边权的最大值 CHANGE x y:将第x条边的权 ...

  4. 计蒜客 - Distance on the tree(树链剖分+离线处理+线段树)

    题目链接:点击查看 题目大意:给出一颗含有n个节点的树,每条边都有权值,现在给出m个询问,每次询问的格式为u,v,w,我们需要求出在路径u-v上,边权小于等于w的边的个数 题目分析:因为一开始不会主席 ...

  5. HDU - 3804 Query on a tree(树链剖分+线段树+离线处理)

    题目链接:点击查看 题目大意:给出一棵树,每条边上都有一个权值,给出m个查询:a,b:问从点1到点a的唯一路径上,在边权小于等于b的边中选出边权最大的值输出,若没有符合条件的边则输出-1: 题目分析: ...

  6. SPOJ 375 query on a tree 树链剖分

    题意: 给一棵树型数据结构 ①支持修改边的权值      ②支持成段边权最值查询 树链剖分入门题. 树链剖分+线段树 用的notonlysuccess的线段树--不开结构体事先预处理的那种 我以前写的 ...

  7. HDU 5044 Tree 树链剖分

    树链剖分离线处理所有的增加操作.考虑如果在线性结构上面处理这样的问题,只要把增加区域的起始点+w,结束点的后面一个点-w,最终输出答案的时候只要扫描一遍就好了,现在通过树链剖分把树转化为类似的线性结构 ...

  8. Tree(树链剖分+线段树延迟标记)

    Tree http://poj.org/problem?id=3237 Time Limit: 5000MS   Memory Limit: 131072K Total Submissions: 12 ...

  9. SPOJ Query on a tree 树链剖分 边修改

    链接 提交链接 题解 对边的修改算到点上 只需要修改下面的地方 代码 #include<bits/stdc++.h> #define N 10010 #define INF 0x3f3f3 ...

最新文章

  1. IIS 500错误,一步帮你搞定.
  2. null对象 java_java中当给一个对象赋值为null时发生了什么
  3. ASP.NET中MVC默认模板的项目结构
  4. 2小时撸完代码之后,所有程序员都逃不过的一天... (强共鸣)
  5. 安装在谷歌axure小工具
  6. play @Before 的使用
  7. Redhat或者Centos手动安装Vim,
  8. 性能提升五十倍:消息队列延时聚合通知的重要性
  9. 【转】《风雨哈佛路》观后感
  10. Atitit. Atiposter 发帖机 新特性 poster new feature v11  .docx
  11. 软件开发的11种模式
  12. ret2text涉及到的堆栈平衡问题
  13. 商城系统mysql数据表设计_购物商城数据库设计-商品表设计
  14. 下列各命令中可以在计算机屏幕上,下列各命令中,可以在计算机屏幕上放映演示文稿的是()。...
  15. 【强制转换】 | PTA 7.1厘米换算英尺英寸
  16. 18.网络技术——BGP的原理+实验题(后附练习题)
  17. html基础-style样式
  18. php音视频同步,FFMPEG转码音视频不同步情况总结
  19. 语音怎么翻译成文字的?
  20. 运筹学 ——线性规划之单纯形法

热门文章

  1. Vcenter一次性将服务器四个网卡从端口组迁移到分布式交换机的方法
  2. 关于Unity中调试C#的方法
  3. 如何成为一个合格的 Java程序员
  4. myeclips/eclipse配置总结(根据网络整理)
  5. 面试题:四种Java线程池用法解析 !=!=未看
  6. 与 Linux 一起学习:学习地理
  7. DB2安全(一)——概述
  8. shell脚本 - 快速到达目录
  9. 在WebView中如何让JS与Java安全地互相调用
  10. Mongodb-初步了解