POJ3237 Tree
| Time Limit: 5000MS | Memory Limit: 131072K | |
| Total Submissions: 2158 | Accepted: 574 |
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
-------------------------------------------------------------
题目大意:指定一颗树上有3个操作:询问操作,询问a点和b点之间的路径上最长的那条边的长度;取反操作,将a点和b点之间的路径权值都取相反数;变化操作,把某条边的权值变成指定的值。
解体思路:这个思路很明显的路径剖分,完全就是来练写路径剖分的。路径剖分讲的比较好的:http://blog.sina.com.cn/s/blog_7a1746820100wp67.html。
就是从来没写过,写得蛋疼,洋洋洒洒5400B,代码风格全然丧失,还好没有出大错误,不然改都没法改。
#include <stdio.h>
#include <string.h>
#include <iostream>
#define clr(a,b) memset(a,b,sizeof(a))
using namespace std;
const int N=10005,M=60005,inf=0x3f3f3f3f;
int n,eid,head[N],ed[N<<1],val[N<<1],nxt[N<<1];
int fa[N],top[N],dep[N],siz[N],id[N],son[N],nid,w[N],p[N];
int le[M],ri[M],rate[M],lazy[M],flag[M],minn[M],maxx[M];
char s[10];
void addedge(int s,int e,int v){
ed[eid]=e;val[eid]=v;nxt[eid]=head[s];head[s]=eid++;
}
/*第一次dfs,确定dep,siz,son,fa*/
void dfs1(int s,int f,int d){
fa[s]=f;dep[s]=d;siz[s]=1;son[s]=-1;
for(int i=head[s];~i;i=nxt[i]){
int e=ed[i];if(e==f)continue;
dfs1(e,s,d+1);siz[s]+=siz[e];p[e]=i;
if(son[s]==-1||siz[e]>siz[son[s]])son[s]=e;
}
}
/*第二次dfs,确定每条边在线段树中的位置(其实只要重边在线段树
里面就好了,但是为了写代码方便,就把所有的边加到线段树了,但保证
了重链是在一起的)*/
void dfs2(int s,int f){
id[s]=++nid;if(~p[s])w[nid]=val[p[s]];
if(!top[s])top[s]=s;
if(~son[s]){top[son[s]]=top[s];dfs2(son[s],s);}
for(int i=head[s];~i;i=nxt[i])
if(ed[i]!=f&&ed[i]!=son[s])dfs2(ed[i],s);
}
void build(int l,int r,int rt){
le[rt]=l;ri[rt]=r;int mid=(l+r)>>1;
rate[rt]=1;lazy[rt]=flag[rt]=0;
if(l==r){
maxx[rt]=minn[rt]=w[l];return ;
}
build(l,mid,rt<<1);build(mid+1,r,rt<<1|1);
minn[rt]=min(minn[rt<<1],minn[rt<<1|1]);
maxx[rt]=max(maxx[rt<<1],maxx[rt<<1|1]);
}
void update(int l,int r,int rt,int a,int b,int c){
if(l==le[rt]&&r==ri[rt]){
if(a==-1){
int k=maxx[rt];maxx[rt]=-minn[rt];
minn[rt]=-k;rate[rt]*=-1;lazy[rt]=-lazy[rt];
}
if(c)lazy[rt]=maxx[rt]=minn[rt]=0;
lazy[rt]+=b;flag[rt]=1;
maxx[rt]+=b;minn[rt]+=b;
return ;
}
if(le[rt]==ri[rt])return ;
int mid=(le[rt]+ri[rt])>>1;
if(flag[rt]){
update(le[rt],mid,rt<<1,rate[rt],lazy[rt],0);
update(mid+1,ri[rt],rt<<1|1,rate[rt],lazy[rt],0);
rate[rt]=1;lazy[rt]=flag[rt]=0;
}
if(r<=mid)update(l,r,rt<<1,a,b,c);
else if(l>mid)update(l,r,rt<<1|1,a,b,c);
else{
update(l,mid,rt<<1,a,b,c);update(mid+1,r,rt<<1|1,a,b,c);
}
minn[rt]=min(minn[rt<<1],minn[rt<<1|1]);
maxx[rt]=max(maxx[rt<<1],maxx[rt<<1|1]);
}
int query(int l,int r,int rt,int a,int b){
if(l==le[rt]&&r==ri[rt])return max(maxx[rt]*a,minn[rt]*a)+b;
int mid=(le[rt]+ri[rt])>>1;
b+=lazy[rt]*a;a*=rate[rt];
if(r<=mid)return query(l,r,rt<<1,a,b);
else if(l>mid)return query(l,r,rt<<1|1,a,b);
return max(query(l,mid,rt<<1,a,b),query(mid+1,r,rt<<1|1,a,b));
}
int main(){
// freopen("/home/axorb/in","r",stdin);
int T;scanf("%d",&T);
while(T--){
eid=0;clr(head,-1);
scanf("%d",&n);
for(int i=1;i<n;i++){
int a,b,c;scanf("%d%d%d",&a,&b,&c);
addedge(a,b,c);addedge(b,a,c);
}
p[1]=-1;dfs1(1,1,1);
nid=-1;clr(top,0);dfs2(1,1);
build(1,nid,1);
while(scanf("%s",s),s[0]!='D'){
int a,b;scanf("%d%d",&a,&b);
if(s[0]=='N'){
while(a!=b){
int f1=top[a],f2=top[b];
if(f1!=f2){
if(dep[f1]>dep[f2]){
if(f1==a)update(id[f1],id[f1],1,-1,0,0),a=fa[a];
else update(id[f1]+1,id[a],1,-1,0,0),a=f1;
}
else{
if(f2==b)update(id[f2],id[f2],1,-1,0,0),b=fa[b];
else update(id[f2]+1,id[b],1,-1,0,0),b=f2;
}
}
else{
if(dep[a]>dep[b])update(id[b]+1,id[a],1,-1,0,0);
else update(id[a]+1,id[b],1,-1,0,0);
a=b;
}
}
}
else if(s[0]=='C'){
a=(a-1)<<1;
if(p[ed[a]]!=a)a^=1;
update(id[ed[a]],id[ed[a]],1,1,b,1);
}
else{
int maxx=-inf;
while(a!=b){
int f1=top[a],f2=top[b];
if(f1!=f2){
if(dep[f1]>dep[f2]){
if(f1==a){
maxx=max(maxx,query(id[f1],id[f1],1,1,0));
a=fa[a];
}
else{
maxx=max(maxx,query(id[f1]+1,id[a],1,1,0));
a=f1;
}
}
else{
if(f2==b){
maxx=max(maxx,query(id[f2],id[f2],1,1,0));
b=fa[b];
}
else {
maxx=max(maxx,query(id[f2]+1,id[b],1,1,0));
b=f2;
}
}
}
else{
if(dep[a]>dep[b])maxx=max(maxx,query(id[b]+1,id[a],1,1,0));
else maxx=max(maxx,query(id[a]+1,id[b],1,1,0));
a=b;
}
}
printf("%d\n",maxx);
}
}
}
}
浙公网安备 33010602011771号