poj 3237 Tree

题目链接:http://poj.org/problem?id=3237

题意:

给出N个节点的树,每条边有权值。有3种操作:

CHANGE i v 改变第i条边的权值,变成v

NEGATE a b a到b的路径上的每条边的权值取相反数

QUERY a b 找出a到b路径上权值最大的边输出

思路:

权值在边上的树链剖分+线段树单点更新+线段树成段更新+线段树成段询问。

  1 #include <iostream>
  2 #include <cstring>
  3 #include <cstdio>
  4 #include <vector>
  5 #include <algorithm>
  6 using namespace std;
  7 #define lson l, m, rt<<1
  8 #define rson m+1, r, rt<<1|1
  9 #define maxn 10010
 10 struct Node
 11 {
 12     int to, val;
 13     Node(int t, int v)
 14     {
 15         to = t; val = v;
 16     }
 17     Node(){}
 18 };
 19 struct Edge
 20 {
 21     int from, to, val;
 22 }e[maxn];
 23 vector <Node> mp[maxn];
 24 int N;
 25 int siz[maxn]; //表示以v为根的子树的节点数
 26 int dep[maxn]; //表示v的深度(根深度为1)
 27 int top[maxn]; //表示v所在的重链的顶端节点
 28 int fa[maxn];  //表示v的父亲
 29 int son[maxn]; //表示与v在同一重链上的v的儿子节点(姑且称为重儿子)
 30 int w[maxn];   //表示v与其父亲节点的连边(姑且称为v的父边)在线段树中的位置
 31 int pos;
 32 int mmax[maxn<<2], mmin[maxn<<2],col[maxn<<2];
 33 void PushUp(int rt)
 34 {
 35     mmax[rt] = max(mmax[rt<<1], mmax[rt<<1|1]);
 36     mmin[rt] = min(mmin[rt<<1], mmin[rt<<1|1]);
 37 }
 38 void PushDown(int rt)
 39 {
 40     if(col[rt])
 41     {
 42         col[rt<<1] ^= 1; col[rt<<1|1] ^= 1;
 43         int tempmax, tempmin;
 44         tempmax = mmax[rt<<1]; tempmin = mmin[rt<<1];
 45         mmax[rt<<1] = -tempmin; mmin[rt<<1] = -tempmax;
 46         tempmax = mmax[rt<<1|1]; tempmin = mmin[rt<<1|1];
 47         mmax[rt<<1|1] = -tempmin; mmin[rt<<1|1] = -tempmax;
 48         col[rt] = 0;
 49     }
 50 }
 51 void build(int l, int r, int rt)
 52 {
 53     col[rt] = 0;
 54     mmax[rt] = -0x3f3f3f3f; 
 55     mmin[rt] = 0x3f3f3f3f; 
 56     
 57     if(l == r) return;
 58     int m = (l+r)>>1;
 59     build(lson);
 60     build(rson);
 61     PushUp(rt);
 62 }
 63 void update(int p, int val, int l, int r, int rt)
 64 {
 65     if(l == r)
 66     {
 67         col[rt] = 0;
 68         mmax[rt] = val; mmin[rt] = val;
 69         return;
 70     }
 71     PushDown(rt);
 72     int m = (l+r)>>1;
 73     if(p <= m) update(p, val, lson);
 74     else update(p, val, rson);
 75     PushUp(rt);
 76 }
 77 void update2(int L, int R, int l, int r, int rt)
 78 {
 79     if(L <= l && R >= r)
 80     {
 81         col[rt] ^= 1;
 82         int tempmax = mmax[rt], tempmin = mmin[rt];
 83         mmax[rt] = -tempmin; mmin[rt] = -tempmax;
 84         return;
 85     }
 86     PushDown(rt);
 87     int m = (l+r)>>1;
 88     if(L <= m) update2(L, R, lson);
 89     if(R > m) update2(L, R, rson);
 90     PushUp(rt);
 91 }
 92 int query(int L, int R, int l, int r, int rt)
 93 {
 94     if(L <= l && R >= r)
 95     {
 96         return mmax[rt];
 97     }
 98     PushDown(rt);
 99     int ret = -0x3f3f3f3f;
100     int m = (l+r)>>1;
101     if(L <= m) ret = max(ret, query(L, R, lson));
102     if(R > m) ret = max(ret, query(L, R, rson));
103     return ret;
104 }
105 int dfs1(int u, int pre, int deep)
106 {
107     siz[u] = 1; dep[u] = deep; fa[u] = pre;
108     int mmax = 0;
109     for(int i = 0; i < mp[u].size(); i++)
110     {
111         if(mp[u][i].to != pre)
112         {
113             int temp = dfs1(mp[u][i].to, u, deep+1);
114             siz[u] += temp;
115             if(son[u] == -1 || temp >= mmax) son[u] = mp[u][i].to;
116         }
117     }
118     return siz[u];
119 }
120 void dfs2(int u, int val)
121 {
122     top[u] = val;
123     if(son[u] != -1)  //如果不是叶子节点,线段树中,v的重边应当在v的父边的后面
124     {
125         w[u] = pos++;
126         dfs2(son[u], val);
127     }
128     else if(son[u] == -1)
129     {
130         w[u] = pos++;
131         return;
132     }
133     for(int i = 0; i < mp[u].size(); i++)
134     {
135         if(mp[u][i].to != son[u] && mp[u][i].to != fa[u]) dfs2(mp[u][i].to, mp[u][i].to);//对于v的各个轻儿子u,top[u] = u
136     }
137 }
138 int find(int u, int v)
139 {
140     int f1 = top[u], f2 = top[v];
141     int temp = -0x3f3f3f3f;
142     while(f1 != f2)
143     {
144         if(dep[f1] < dep[f2])  //设dep[f1] >= dep[f2]
145         {
146             swap(f1, f2);
147             swap(u, v);
148         }
149         temp = max(temp, query(w[f1],w[u], 1, pos-1, 1));
150         u = fa[f1]; f1 = top[u];
151     }
152     if(u == v) return temp;
153     if(dep[u] > dep[v]) swap(u, v);
154     return max(temp, query(w[son[u]], w[v], 1, pos-1, 1));
155 }
156 void Negate(int u, int v)
157 {
158    int f1 = top[u], f2 = top[v];
159    while(f1 != f2)
160    {
161        if(dep[f1] < dep[f2])
162        {
163            swap(f1, f2);
164            swap(u, v);
165        }
166        update2(w[f1], w[u], 1, pos-1, 1);
167        u = fa[f1]; f1 = top[u];
168    } 
169    if(u == v) return;
170    if(dep[u] > dep[v]) swap(u, v);
171    update2(w[son[u]], w[v], 1, pos-1, 1);
172 }
173 int main() 
174 {
175    // freopen("in.txt", "r", stdin);
176     //freopen("out.txt", "w", stdout);
177     int T; scanf("%d", &T);
178     while(T--)
179     {
180         scanf("%d", &N);
181         pos = 0; memset(son, -1, sizeof(son));
182         for(int i = 1; i <= N; i++) mp[i].clear();
183         for(int i = 1; i <= N-1; i++)
184         {
185             scanf("%d%d%d", &e[i].from, &e[i].to, &e[i].val);
186             mp[e[i].from].push_back(Node(e[i].to, e[i].val));
187             mp[e[i].to].push_back(Node(e[i].from, e[i].val));
188         }
189         dfs1(1, -1, 1);
190         dfs2(1, 1);
191         build(1, pos-1, 1);
192         for(int i = 1; i <= N-1; i++)
193         {
194             if(dep[e[i].from] > dep[e[i].to])
195             {
196                 swap(e[i].from, e[i].to);
197             }
198             update(w[e[i].to], e[i].val, 1, pos-1, 1);
199         }
200         char op[15];
201         while(scanf("%s", op))
202         {
203             if(op[0] == 'D') break;
204             int a, b; scanf("%d%d", &a, &b);
205             if(op[0] == 'Q') printf("%d\n", find(a, b));
206             else if(op[0] == 'C') update(w[e[a].to], b, 1, pos-1, 1);
207             else if(op[0] == 'N') Negate(a, b);
208 
209         }
210     }
211 
212     return 0;
213 }

 

posted @ 2015-10-22 18:48  下周LGD该赢了吧  阅读(181)  评论(0编辑  收藏  举报