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); } } } }