码迷,mamicode.com
首页 > 其他好文 > 详细

【POJ3237】Tree(树链剖分+线段树)

时间:2016-05-08 15:18:19      阅读:240      评论:0      收藏:0      [点我收藏+]

标签:

Description

You are given a tree with N nodes. The tree’s nodes are numbered 1 through N and its edges are numbered 1 throughN − 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:

CHANGEiv Change the weight of the ith edge to v
NEGATEab Negate the weight of every edge on the path from a to b
QUERYab 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

1

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

Sample Output

1
3
 

 【题意】

指定一颗树上有3个操作:

  询问操作,询问a点和b点之间的路径上最长的那条边的长度;

  取反操作,将a点和b点之间的路径权值都取相反数;

  变化操作,把某条边的权值x变成指定的值。

 

【分析】

  人生第一道树剖题,调了好久啊,200+的代码还打了对拍= =

  就是裸的树链剖分+线段树啦。

  就是线段树打得不够熟练所以调了那么久,lazy标记不大会用~~

  

  树剖的主要过程就是两次的dfs,第一次求fa,第二次求top。询问过程就是一直跳,跳到两个东西在一条重链上去。

  因为某种特殊性质,所以他很快。。

 

代码如下:

技术分享
  1 #include<cstdio>
  2 #include<cstdlib>
  3 #include<cstring>
  4 #include<iostream>
  5 #include<algorithm>
  6 using namespace std;
  7 #define Maxn 10010
  8 #define INF 100000000
  9 
 10 int fa[Maxn],first[Maxn],size[Maxn],dep[Maxn],son[Maxn];
 11 int w[Maxn],top[Maxn];int wl;
 12 int b[Maxn][5];
 13 
 14 struct node
 15 {
 16     int x,y,c,next;
 17 }t[2*Maxn];int len;
 18 
 19 struct nnode
 20 {
 21     int l,r,lc,rc,mx,mn;
 22     bool lazy;
 23 }tr[2*Maxn];int tl;
 24 
 25 int mymax(int x,int y) {return x>y?x:y;}
 26 int mymin(int x,int y) {return x<y?x:y;}
 27 
 28 void ins(int x,int y,int c)
 29 {
 30     t[++len].x=x;t[len].y=y;t[len].c=c;
 31     t[len].next=first[x];first[x]=len;
 32 }
 33 
 34 void dfs1(int x,int f)
 35 {
 36     fa[x]=f;dep[x]=dep[f]+1;size[x]=1;
 37     son[x]=0;
 38     for(int i=first[x];i;i=t[i].next) if(t[i].y!=f)
 39     {
 40         dfs1(t[i].y,x);
 41         size[x]+=size[t[i].y];
 42         if(size[t[i].y]>size[son[x]]) son[x]=t[i].y;
 43     }
 44 }
 45 
 46 void dfs2(int x,int tp)
 47 {
 48     w[x]=++wl;
 49     top[x]=tp;
 50     if(size[x]!=1) dfs2(son[x],tp);
 51     for(int i=first[x];i;i=t[i].next) if(t[i].y!=fa[x]&&t[i].y!=son[x])
 52     {
 53         dfs2(t[i].y,t[i].y);
 54     }
 55 }
 56 
 57 int build(int l,int r)
 58 {
 59     int x=++tl;
 60     tr[x].l=l;tr[x].r=r;tr[x].mx=-INF;tr[x].mn=INF;tr[x].lazy=0;
 61     if(l!=r)
 62     {
 63         int mid=(l+r)>>1;
 64         tr[x].lc=build(l,mid);
 65         tr[x].rc=build(mid+1,r);
 66     }
 67     return x;
 68 }
 69 
 70 void upd(int x)
 71 {
 72     if(!tr[x].lazy) return;
 73     tr[x].lazy=0;
 74     int a=tr[x].mx;
 75     tr[x].mx=-tr[x].mn;tr[x].mn=-a;
 76     if(tr[x].l==tr[x].r) return;
 77     tr[tr[x].lc].lazy=!tr[tr[x].lc].lazy;
 78     tr[tr[x].rc].lazy=!tr[tr[x].rc].lazy;
 79 }
 80 
 81 void change(int x,int y,int c)
 82 {
 83     upd(x);
 84     if(tr[x].l==tr[x].r)
 85     {
 86         tr[x].mx=c;
 87         tr[x].mn=c;
 88         return;
 89     }
 90     int mid=(tr[x].l+tr[x].r)>>1;
 91     if(y<=mid) change(tr[x].lc,y,c);
 92     else change(tr[x].rc,y,c);
 93     upd(tr[x].lc);upd(tr[x].rc);
 94     tr[x].mx=mymax(tr[tr[x].lc].mx,tr[tr[x].rc].mx);
 95     tr[x].mn=mymin(tr[tr[x].lc].mn,tr[tr[x].rc].mn);
 96 }
 97 
 98 int qtree(int x,int l,int r)
 99 {
100     upd(x);
101     if(tr[x].l==l&&tr[x].r==r) return tr[x].mx;
102     int mid=(tr[x].l+tr[x].r)>>1;
103     if(r<=mid) return qtree(tr[x].lc,l,r);
104     if(l>mid) return qtree(tr[x].rc,l,r);
105     return mymax(qtree(tr[x].lc,l,mid),qtree(tr[x].rc,mid+1,r));
106 }
107 
108 int query(int x,int y)
109 {
110     int tmp=-INF;
111     int f1=top[x],f2=top[y];
112     while(f1!=f2)
113     {
114         if(dep[f1]<dep[f2]) 
115         {
116             swap(f1,f2);
117             swap(x,y);
118         }
119         tmp=mymax(qtree(1,w[f1],w[x]),tmp);
120         x=fa[f1];
121         f1=top[x];
122     }
123     if(x==y) return tmp;
124     if(dep[x]<dep[y]) swap(x,y);
125     return mymax(tmp,qtree(1,w[son[y]],w[x]));
126 }
127 
128 void change2(int x,int l,int r)
129 {
130     upd(x);
131     if(tr[x].l==l&&tr[x].r==r)
132     {
133         tr[x].lazy=!tr[x].lazy;
134         upd(x);
135         return;
136     }
137     int mid=(tr[x].l+tr[x].r)>>1;
138     if(r<=mid) change2(tr[x].lc,l,r);
139     else if(l>mid) change2(tr[x].rc,l,r);
140     else
141     {
142         change2(tr[x].lc,l,mid);
143         change2(tr[x].rc,mid+1,r);
144     }
145     upd(tr[x].lc);upd(tr[x].rc);
146     tr[x].mx=mymax(tr[tr[x].lc].mx,tr[tr[x].rc].mx);
147     tr[x].mn=mymin(tr[tr[x].lc].mn,tr[tr[x].rc].mn);
148 }
149 
150 void negate1(int x,int y)
151 {
152     int f1=top[x],f2=top[y];
153     while(f1!=f2)
154     {
155         if(dep[f1]<dep[f2]) 
156         {
157             swap(f1,f2);
158             swap(x,y);
159         }
160         change2(1,w[f1],w[x]);
161         x=fa[f1];
162         f1=top[x];
163     }
164     if(x==y) return;
165     if(dep[x]<dep[y]) swap(x,y);
166     change2(1,w[son[y]],w[x]);
167 }
168 
169 int main()
170 {
171     int T;
172     scanf("%d",&T);
173     while(T--)
174     {
175         int n;
176         scanf("%d",&n);
177         memset(first,0,sizeof(first));
178         len=0;
179         for(int i=1;i<n;i++)
180         {
181             int x,y,c;
182             scanf("%d%d%d",&x,&y,&c);
183             b[i][0]=x;b[i][1]=y;b[i][2]=c;
184             ins(x,y,c);ins(y,x,c);
185         }
186         dep[0]=0;size[0]=0;
187         dfs1(1,0);wl=0;
188         dfs2(1,1);
189         char s[10];
190         tl=0;
191         build(1,wl);
192         for(int i=1;i<n;i++)
193         {
194             if(dep[b[i][0]]<dep[b[i][1]]) swap(b[i][0],b[i][1]);
195             change(1,w[b[i][0]],b[i][2]);
196         }
197         while(1)
198         {
199             scanf("%s",s);
200             if(s[0]==D) break;
201             if(s[0]==Q)
202             {
203                 int x,y;
204                 scanf("%d%d",&x,&y);
205                 printf("%d\n",query(x,y));
206             }
207             else if(s[0]==C)
208             {
209                 int x,y;
210                 scanf("%d%d",&x,&y);
211                 change(1,w[b[x][0]],y);//单点修改
212             }
213             else
214             {
215                 int x,y;
216                 scanf("%d%d",&x,&y);
217                 negate1(x,y);
218             }
219         }
220     }
221     return 0;
222 }
[POJ3237]

 

2016-05-08 14:50:31

 

【POJ3237】Tree(树链剖分+线段树)

标签:

原文地址:http://www.cnblogs.com/Konjakmoyu/p/5470636.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!