Time Limit: 5000MS | Memory Limit: 131072K | |
Total Submissions: 7384 | Accepted: 2001 |
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
/*
poj3237 树链部分
感觉是比较不错的题目,主要是线段树掌握不怎么好导致一直有问题。
查询最大值 + 修改边 + 区间置反
先处理出树链,然后再上值
push_up 和 push_down函数
hhh-2016-2-2 3:46:58
*/ #include <functional>
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <Map>
using namespace std;
typedef long long ll;
typedef long double ld; using namespace std; const int maxn = 100010; struct node
{
int to,next;
} edge[maxn*2]; int head[maxn];
int top[maxn]; //链的顶端节点
int far[maxn]; //父亲
int dep[maxn]; //深度
int num[maxn]; //表示以x为根的子树的节点数
int p[maxn]; //p[u]表示边u所在的位置
int fp[maxn]; //与p相对应
int son[maxn]; //重儿子
int tot,pos;
void addedge(int u,int v)
{
edge[tot].to = v;
edge[tot].next = head[u];
head[u] = tot ++;
} void dfs(int u,int fa,int d) //先处理出重儿子、dep、far、num
{
dep[u] = d;
far[u] = fa;
num[u] = 1;
for(int i = head[u]; i != -1; i = edge[i].next)
{
int v = edge[i].to;
if(v != fa)
{
dfs(v,u,d+1);
num[u] += num[v];
if(son[u] == -1 || num[v] > num[son[u]])
son[u] = v;
}
}
} void getpos(int u,int sp)
{
top[u] = sp;
p[u] = pos++;
fp[p[u]] = u;
if(son[u] == -1) return ;
getpos(son[u],sp);
for(int i = head[u]; i != -1; i = edge[i].next)
{
int v = edge[i].to;
if(v != far[u] && v != son[u])
getpos(v,v);
}
} struct Node
{
int l,r;
int flag;
int Max,Min;
} segtree[maxn*3]; void build(int i,int l,int r)
{
segtree[i].l = l;
segtree[i].r = r;
segtree[i].Max = 0;
segtree[i].Min = 0;
segtree[i].flag = 0;
if(l == r)
return ;
int mid = (l+r)/2;
build(i<<1,l,mid);
build((i<<1)|1,mid+1,r);
} void push_up(int i)
{
segtree[i].Max = max(segtree[i<<1].Max,segtree[(i<<1)|1].Max);
segtree[i].Min = min(segtree[i<<1].Min,segtree[(i<<1)|1].Min);
} void push_down(int i)
{
if(segtree[i].l == segtree[i].r)
return ;
if(segtree[i].flag)
{
segtree[i<<1].Max = -segtree[i<<1].Max;
segtree[i<<1].Min = -segtree[i<<1].Min;
swap(segtree[i<<1].Max,segtree[i<<1].Min);
segtree[i<<1].flag ^= 1; segtree[(i<<1)|1].Max = -segtree[(i<<1)|1].Max;
segtree[(i<<1)|1].Min = -segtree[(i<<1)|1].Min;
segtree[(i<<1)|1].flag ^= 1;
swap(segtree[(i<<1)|1].Max,segtree[(i<<1)|1].Min); segtree[i].flag = 0;
}
} void update(int i,int k,int val)
{
if(segtree[i].l == k && segtree[i].r == k)
{
segtree[i].Max = val;
segtree[i].Min = val;
segtree[i].flag = 0;
return ;
}
push_down(i);
int mid = (segtree[i].l+segtree[i].r)>>1;
if(k <= mid) update(i<<1,k,val);
else update((i<<1)|1,k,val);
push_up(i);
} void negat(int i,int l,int r)
{
if((segtree[i].l == l && segtree[i].r == r))
{
segtree[i].Max = -segtree[i].Max;
segtree[i].Min = -segtree[i].Min;
swap(segtree[i].Max,segtree[i].Min);
segtree[i].flag ^= 1;
return;
}
push_down(i);
int mid = (segtree[i].l+segtree[i].r)>>1;
if(r <= mid) negat(i<<1,l,r);
else if(l > mid) negat((i<<1)|1,l,r);
else
{
negat(i<<1,l,mid);
negat((i<<1)|1,mid+1,r);
}
push_up(i);
} int query(int i,int l,int r)
{
if(segtree[i].l == l && segtree[i].r == r)
{
return segtree[i].Max;
}
push_down(i);
int mid = (segtree[i].l+segtree[i].r)>>1;
if(r <= mid) return query(i<<1,l,r);
else if(l > mid) return query((i<<1)|1,l,r);
else return max(query(i<<1,l,mid),query((i<<1)|1,mid+1,r));
push_up(i);
} int fin(int l,int r)
{
int f1 = top[l];
int f2 = top[r];
int tt = -100000000;
while(f1 != f2)
{
if(dep[f1] < dep[f2])
{
swap(f1,f2);
swap(l,r);
}
tt = max(query(1,p[f1],p[l]),tt);
l = far[f1];
f1 = top[l];
}
if(l == r)
return tt;
if(dep[l] > dep[r]) swap(l,r);
return max(tt,query(1,p[son[l]],p[r]));
} void change(int l,int r)
{
int f1 = top[l];
int f2 = top[r];
while(f1 != f2)
{
if(dep[f1] < dep[f2])
{
swap(f1,f2);
swap(l,r);
}
negat(1,p[f1],p[l]);
l = far[f1];
f1 = top[l];
}
if(l == r) return ;
if(dep[l] > dep[r]) swap(l,r);
negat(1,p[son[l]],p[r]);
} void ini()
{
tot = 0;
pos = 1;
memset(head,-1,sizeof(head));
memset(son,-1,sizeof(son));
} int me[maxn][2];
int va[maxn]; int main()
{
int T;
int n;
//freopen("in.txt","r",stdin);
scanf("%d",&T);
while(T--)
{
scanf("%d",&n);
ini();
for(int i = 1; i < n; i++)
{
scanf("%d%d%d",&me[i][0],&me[i][1],&va[i]);
addedge(me[i][0],me[i][1]);
addedge(me[i][1],me[i][0]);
} dfs(1,0,0);
getpos(1,1);
build(1,1,n);
for(int i = 1; i < n; i++)
{
if(dep[me[i][0]] > dep[me[i][1]])
swap(me[i][0],me[i][1]);
update(1,p[me[i][1]],va[i]);
}
char ch[10];
while(scanf("%s",ch) == 1)
{
;
if(ch[0] == 'D') break;
int u,v;
scanf("%d%d",&u,&v);
if(ch[0] == 'Q')
printf("%d\n",fin(u,v));
else if(ch[0] == 'N')
change(u,v);
else
update(1,p[me[u][1]],v);
}
}
return 0;
}