http://poj.org/problem?id=3237
Time Limit: 5000MS | Memory Limit: 131072K | |
Total Submissions: 4206 | Accepted: 1171 |
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
spoj那道题的升级版,多了个区间取反操作,就是线段树要lazy标记下区间是否取反就好,就是代码略长。。
/**
* @author neko01
*/
//#pragma comment(linker, "/STACK:102400000,102400000")
#include <cstdio>
#include <cstring>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <queue>
#include <vector>
#include <cmath>
#include <set>
#include <map>
using namespace std;
typedef long long LL;
#define min3(a,b,c) min(a,min(b,c))
#define max3(a,b,c) max(a,max(b,c))
#define pb push_back
#define mp(a,b) make_pair(a,b)
#define clr(a) memset(a,0,sizeof a)
#define clr1(a) memset(a,-1,sizeof a)
#define dbg(a) printf("%d\n",a)
typedef pair<int,int> pp;
const double eps=1e-9;
const double pi=acos(-1.0);
const int INF=0x3f3f3f3f;
const LL inf=(((LL)1)<<61)+5;
const int N=10005;
struct edge{
int to,next;
}e[N*2];
int head[N],tot;
int num[N];
int son[N];
int fa[N];
int dep[N];
int top[N];
int p[N];
int pos;
void init()
{
tot=pos=0;
clr1(head);
clr1(son);
}
void add(int u,int v)
{
e[tot].to=v;
e[tot].next=head[u];
head[u]=tot++;
}
void dfs1(int u,int pre,int d)
{
num[u]=1;
fa[u]=pre;
dep[u]=d;
for(int i=head[u];i!=-1;i=e[i].next)
{
int v=e[i].to;
if(v!=pre)
{
dfs1(v,u,d+1);
num[u]+=num[v];
if(son[u]==-1||num[v]>num[son[u]])
son[u]=v;
}
}
}
void dfs2(int u,int sp)
{
top[u]=sp;
p[u]=pos++;
if(son[u]!=-1)
dfs2(son[u],sp);
for(int i=head[u];i!=-1;i=e[i].next)
{
int v=e[i].to;
if(v!=son[u]&&v!=fa[u])
dfs2(v,v);
}
}
struct node{
int l,r;
int Max,Min;
int mm; //这段区间是否取反
}tree[N*4];
void build(int x,int l,int r)
{
tree[x].l=l;
tree[x].r=r;
tree[x].mm=tree[x].Max=tree[x].Min=0;
if(l==r) return;
int mid=(l+r)>>1;
build(x<<1,l,mid);
build(x<<1|1,mid+1,r);
}
void push_up(int x)
{
tree[x].Max=max(tree[x<<1].Max,tree[x<<1|1].Max);
tree[x].Min=min(tree[x<<1].Min,tree[x<<1|1].Min);
}
void push_down(int x)
{
if(tree[x].mm)
{
tree[x].mm=0;
tree[x<<1].mm^=1;
tree[x<<1|1].mm^=1;
tree[x<<1].Max*=-1;
tree[x<<1].Min*=-1;
swap(tree[x<<1].Max,tree[x<<1].Min);
tree[x<<1|1].Max*=-1;
tree[x<<1|1].Min*=-1;
swap(tree[x<<1|1].Max,tree[x<<1|1].Min);
}
}
int query(int x,int l,int r)
{
if(tree[x].l==l&&tree[x].r==r)
{
return tree[x].Max;
}
push_down(x);
int mid=(tree[x].l+tree[x].r)>>1;
if(r<=mid) return query(x<<1,l,r);
else if(l>mid) return query(x<<1|1,l,r);
else return max(query(x<<1,l,mid),query(x<<1|1,mid+1,r));
push_up(x);
}
void update1(int x,int k,int val)
{
if(tree[x].l==k&&tree[x].r==k)
{
tree[x].Max=tree[x].Min=val;
tree[x].mm=0;
return;
}
push_down(x);
int mid=(tree[x].l+tree[x].r)>>1;
if(k<=mid) update1(x<<1,k,val);
else update1(x<<1|1,k,val);
push_up(x);
}
void update2(int x,int l,int r)
{
if(tree[x].l==l&&tree[x].r==r)
{
tree[x].Max*=-1;
tree[x].Min*=-1;
swap(tree[x].Max,tree[x].Min);
tree[x].mm^=1;
return;
}
push_down(x);
int mid=(tree[x].l+tree[x].r)>>1;
if(r<=mid)
update2(x<<1,l,r);
else if(l>mid)
update2(x<<1|1,l,r);
else
{
update2(x<<1,l,mid);
update2(x<<1|1,mid+1,r);
}
push_up(x);
}
int getmax(int u,int v)
{
int ans=-INF,f1=top[u],f2=top[v];
while(f1!=f2)
{
if(dep[f1]<dep[f2])
{
swap(f1,f2);
swap(u,v);
}
ans=max(ans,query(1,p[f1],p[u]));
u=fa[f1];
f1=top[u];
}
if(u==v) return ans;
if(dep[u]>dep[v]) swap(u,v);
return max(ans,query(1,p[son[u]],p[v]));
}
void gao(int u,int v) //u到v边权值取反
{
int f1=top[u],f2=top[v];
while(f1!=f2)
{
if(dep[f1]<dep[f2])
{
swap(f1,f2);
swap(u,v);
}
update2(1,p[f1],p[u]);
u=fa[f1];
f1=top[u];
}
if(u==v) return;
if(dep[u]>dep[v]) swap(u,v);
update2(1,p[son[u]],p[v]);
}
int a[N][3];
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
int n;
scanf("%d",&n);
init();
for(int i=1;i<n;i++)
{
scanf("%d%d%d",&a[i][0],&a[i][1],&a[i][2]);
add(a[i][0],a[i][1]);
add(a[i][1],a[i][0]);
}
dfs1(1,0,0);
dfs2(1,1);
build(1,0,pos-1);
for(int i=1;i<n;i++)
{
if(dep[a[i][0]]>dep[a[i][1]])
swap(a[i][0],a[i][1]);
update1(1,p[a[i][1]],a[i][2]);
}
char s[10];
while(~scanf("%s",s))
{
if(s[0]=='D') break;
int u,v;
scanf("%d%d",&u,&v);
if(s[0]=='Q')
printf("%d\n",getmax(u,v));
else if(s[0]=='C')
update1(1,p[a[u][1]],v);
else
gao(u,v);
}
}
return 0;
}