poj 3237 Tree(树链剖分,线段树)

 

Tree
Time Limit: 5000MS   Memory Limit: 131072K
Total Submissions: 7268   Accepted: 1969

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 a, b 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

Source

POJ Monthly--2007.06.03, Lei, Tao

 

【思路】

       树链剖分,线段树。

       又练了一边线段树<_<,bug满天飞T^T,线段树还得再做点题。

       线段树:维护mx mn分别代表线段最大最小值,对于NEGATE操作打一个f标记,作用时直接将mx mn取负后交换即可。注意一下pushdown和maintain。

 

【代码】

 

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<vector>
  4 #include<iostream>
  5 #include<algorithm>
  6 #define FOR(a,b,c) for(int a=(b);a<=(c);a++)
  7 using namespace std;
  8 
  9 const int N = 50000+10;
 10 const int INF = 1e9;
 11 
 12 struct Node { int l,r,mx,mn,f;
 13 }T[N<<1];
 14 struct Edge { 
 15     int u,v,w; 
 16     Edge(int u=0,int v=0,int w=0) :u(u),v(v),w(w) {};
 17 };
 18 int n,q,z,d[N][3];
 19 vector<Edge> es;
 20 vector<int> g[N];
 21 
 22 void adde(int u,int v,int w) {
 23     es.push_back(Edge(u,v,w));
 24     int m=es.size();
 25     g[u].push_back(m-1);
 26 }
 27 //INIT
 28 int top[N],son[N],dep[N],fa[N],siz[N],w[N];
 29 void dfs1(int u) {
 30     son[u]=0; siz[u]=1;
 31     for(int i=0;i<g[u].size();i++) {
 32         int v=es[g[u][i]].v;                                //1
 33         if(v!=fa[u]) {
 34             fa[v]=u , dep[v]=dep[u]+1;
 35             dfs1(v);
 36             siz[u]+=siz[v];
 37             if(siz[v]>siz[son[u]]) son[u]=v;
 38         }
 39     }
 40 }
 41 void dfs2(int u,int tp) {
 42     top[u]=tp; w[u]=++z;
 43     if(son[u]) dfs2(son[u],tp);
 44     for(int i=0;i<g[u].size();i++) {
 45         int v=es[g[u][i]].v;
 46         if(v!=fa[u] && v!=son[u]) dfs2(v,v);
 47     }
 48 }
 49 //SEGMENT TREE 
 50 //标记 该结点已被作用而子结点仍未作用 
 51 //pushdown 作用于访问节点 即只要访问就pushdown 
 52 void pushdown(int u) {    //下传标记 同时作用于子结点 
 53     if(T[u].f && T[u].l<T[u].r) {
 54         int lc=u<<1,rc=lc|1;
 55         T[u].f=0;
 56         T[lc].f^=1 ,T[rc].f^=1;
 57         int t;
 58         t=T[lc].mn,T[lc].mn=-T[lc].mx,T[lc].mx=-t;
 59         t=T[rc].mn,T[rc].mn=-T[rc].mx,T[rc].mx=-t;
 60     }
 61 }
 62 void maintain(int u) {
 63     T[u].mx=max(T[u<<1].mx,T[u<<1|1].mx);
 64     T[u].mn=min(T[u<<1].mn,T[u<<1|1].mn);
 65 }
 66 void build(int u,int L,int R) {
 67     T[u].l=L,T[u].r=R;
 68     T[u].mn=INF , T[u].mx=-INF , T[u].f=0;
 69     if(L==R) return ;                                        //2
 70     int M=(L+R)>>1;
 71     build(u<<1,L,M) , build(u<<1|1,M+1,R);
 72 }
 73 void change(int u,int r,int x) {
 74     pushdown(u);                                            //6
 75     if(T[u].l==T[u].r) T[u].mn=T[u].mx=x;
 76     else {
 77         int M=(T[u].l+T[u].r)>>1;                            //3
 78         if(r<=M) change(u<<1,r,x);
 79         else change(u<<1|1,r,x);
 80         maintain(u);
 81     }
 82 }
 83 void Negate(int u,int L,int R) {
 84     pushdown(u);
 85     if(L<=T[u].l && T[u].r<=R) {//打标记 同时作用于当前结点 
 86         T[u].f=1; 
 87         int t; t=T[u].mn,T[u].mn=-T[u].mx,T[u].mx=-t;        //4
 88     }
 89     else {
 90         int M=(T[u].l+T[u].r)>>1;
 91         if(L<=M) Negate(u<<1,L,R);
 92         if(M<R) Negate(u<<1|1,L,R);
 93         maintain(u);
 94     }
 95 }
 96 int query(int u,int L,int R) {
 97     pushdown(u);
 98     if(L<=T[u].l && T[u].r<=R) return T[u].mx;
 99     else {
100         int M=(T[u].l+T[u].r)>>1;
101         int ans=-INF;
102         if(L<=M) ans=max(ans,query(u<<1,L,R));
103         if(M<R) ans=max(ans,query(u<<1|1,L,R));
104         return ans;
105     }
106 }
107 
108 //树链剖分
109 void modify(int u,int v) {
110     while(top[u]!=top[v]) {
111         if(dep[top[u]]<dep[top[v]]) swap(u,v);
112         Negate(1,w[top[u]],w[u]);
113         u=fa[top[u]];
114     }
115     if(u==v) return ;
116     if(dep[u]>dep[v]) swap(u,v);
117     Negate(1,w[son[u]],w[v]);                                //5
118 }
119 int query(int u,int v) {
120     int mx=-INF;
121     while(top[u]!=top[v]) {
122         if(dep[top[u]]<dep[top[v]]) swap(u,v);
123         mx=max(mx,query(1,w[top[u]],w[u]));
124         u=fa[top[u]];
125     }
126     if(u==v) return mx;
127     if(dep[u]>dep[v]) swap(u,v);
128     mx=max(mx,query(1,w[son[u]],w[v]));
129     return mx;
130 }
131 
132 void read(int& x) {
133     char c=getchar();
134     while(!isdigit(c)) c=getchar();
135     x=0;
136     while(isdigit(c))
137         x=x*10+c-'0' , c=getchar();
138 }
139 int main() {
140     //freopen("in.in","r",stdin);
141     //freopen("out.out","w",stdout);
142     int T; read(T);
143     while(T--) {
144         read(n);
145         z=0; es.clear();
146         FOR(i,0,n) g[i].clear();
147         int u,v,c;
148         FOR(i,1,n-1) {
149             read(u),read(v),read(c);
150             d[i][0]=u,d[i][1]=v,d[i][2]=c;
151             adde(u,v,c),adde(v,u,c);
152         }
153         dfs1(1),dfs2(1,1);
154         build(1,1,z);
155         FOR(i,1,n-1) {
156             if(dep[d[i][1]]<dep[d[i][0]]) swap(d[i][0],d[i][1]);
157             change(1,w[d[i][1]],d[i][2]);
158         }
159          char s[10];
160         while(scanf("%s",s)==1 && s[0]!='D') {
161             read(u),read(v);
162             if(s[0]=='C') change(1,w[d[u][1]],v);
163             else if(s[0]=='N') modify(u,v);
164             else printf("%d\n",query(u,v));
165         }
166     }
167     return 0;
168 }

 

你可能感兴趣的:(poj 3237 Tree(树链剖分,线段树))