传送门:http://oj.cnuschool.org.cn/oj/home/problem.htm?problemID=979
WZJ的数据结构(六) |
难度级别:D; 运行时间限制:1000ms; 运行空间限制:51200KB; 代码长度限制:2000000B |
试题描述
|
给你一棵N个节点的无根树,边之间有权值。请你设计一个数据结构,进行以下两种操作: 1.修改:给你a、b,将第a条边的权值改为b。 2.询问:给你a、b,输出从a到b路径上的最大值、最小值与权值和,如果a=b,输出"error"。 |
输入
|
第一行为一个正整数N。
接下来N-1行为每一条边,每行3个正整数a,b,c,表示有一条从a到b权值为c的边(从1开始编号)。 第N+1行为一个正整数Q,表示Q次操作。 接下来Q行为每一次询问,每行3个正整数t,a,b,若t=1表示询问,t=0表示修改。 |
输出
|
对于每一次询问,输出三个正整数,即最大值、最小值与权值和,如果a=b,输出"error"。
|
输入示例
|
5
1 2 4 1 4 5 3 4 6 2 5 7 4 1 1 5 1 2 5 0 1 2 1 1 5 |
输出示例
|
7 4 11
7 7 7 7 2 9 |
其他说明
|
1<=N,Q<=50000
1<=c<=1000 询问中的1<=a,b<=N 修改中的1<=a<=N-1,1<=b<=1000 |
题解:懒得写树链剖分了LCT走起
1 #include<iostream> 2 #include<cstdio> 3 #include<cmath> 4 #include<algorithm> 5 #include<queue> 6 #include<cstring> 7 #define PAU putchar(' ') 8 #define ENT putchar(' ') 9 using namespace std; 10 const int maxn=100000+10,inf=-1u>>1; 11 inline int read(){ 12 int x=0,sig=1;char ch=getchar(); 13 while(!isdigit(ch)){if(ch=='-')sig=-1;ch=getchar();} 14 while(isdigit(ch))x=10*x+ch-'0',ch=getchar(); 15 return x*=sig; 16 } 17 inline void write(int x){ 18 if(x==0){putchar('0');return;}if(x<0)putchar('-'),x=-x; 19 int len=0,buf[15];while(x)buf[len++]=x%10,x/=10; 20 for(int i=len-1;i>=0;i--)putchar(buf[i]+'0');return; 21 } 22 struct node { 23 int x,mi,mx,sm,set;bool rev; 24 node *ch[2],*fa; 25 inline void add_rev_tag(){ 26 swap(ch[0],ch[1]);rev^=1;return; 27 } 28 inline void add_set_tag(int a){ 29 x=set=a; 30 if(mi!=inf) mi=set; 31 if(mx!=-inf) mx=set; 32 } 33 inline void down(){ 34 if(rev){ 35 if(ch[0]) ch[0]->add_rev_tag(); 36 if(ch[1]) ch[1]->add_rev_tag(); 37 rev=0; 38 } 39 if(set){ 40 if(ch[0]) ch[0]->add_set_tag(set); 41 if(ch[1]) ch[1]->add_set_tag(set); 42 set=0; 43 } 44 return; 45 } 46 inline void update(){ 47 sm=x;mi=inf;mx=-inf; 48 if(ch[0]) sm+=ch[0]->sm,mi=min(mi,ch[0]->mi),mx=max(mx,ch[0]->mx); 49 if(ch[1]) sm+=ch[1]->sm,mi=min(mi,ch[1]->mi),mx=max(mx,ch[1]->mx); 50 if(!x) return; 51 mi=min(x,mi); 52 mx=max(x,mx); 53 return; 54 } 55 }lct[maxn]; 56 inline int get_parent(node *x,node *&fa){return (fa=x->fa)?fa->ch[0]==x?0:fa->ch[1]==x?1:-1:-1;} 57 inline void rotate(node *x){ 58 int t1,t2; 59 node *fa,*gfa; 60 t1=get_parent(x,fa); 61 t2=get_parent(fa,gfa); 62 if ((fa->ch[t1]=x->ch[t1^1])) fa->ch[t1]->fa=fa; 63 x->ch[t1^1]=fa;fa->fa=x;x->fa=gfa; 64 if (t2!=-1) gfa->ch[t2]=x; 65 fa->update();return; 66 } 67 inline void pushdown(node *x){ 68 static node *stack[maxn]; 69 int cnt=0; 70 while(1){ 71 stack[cnt++]=x; 72 node *fa=x->fa; 73 if (!fa || (fa->ch[0]!=x && fa->ch[1]!=x)) break; 74 x=fa; 75 } 76 while(cnt--) stack[cnt]->down(); 77 return; 78 } 79 inline node * splay(node *x){ 80 pushdown(x); 81 while(1){ 82 int t1,t2; 83 node *fa,*gfa; 84 t1=get_parent(x,fa); 85 if(t1==-1) break; 86 t2=get_parent(fa,gfa); 87 if(t2==-1){ 88 rotate(x);break; 89 } else if (t1==t2){ 90 rotate(fa);rotate(x); 91 } else{ 92 rotate(x);rotate(x); 93 } 94 } 95 x->update(); 96 return x; 97 } 98 inline node * access(node *x){ 99 node *ret=NULL; 100 while (x) splay(x)->ch[1]=ret,(ret=x)->update(),x=x->fa; 101 return ret; 102 } 103 inline void makeroot(int x){access(lct+x)->add_rev_tag();} 104 inline void link(int u,int v){ 105 makeroot(u);splay(lct+u)->fa=lct+v;return; 106 } 107 int n,q; 108 int main(){ 109 n=read(); 110 int i; 111 int lim=n<<1; 112 for(i=1;i<=lim;i++) { 113 lct[i]=(node){0,inf,-inf,0,0,0}; 114 } 115 for(i=1;i<n;i++){ 116 int u,v,w; 117 u=read();v=read(); 118 link(u,i+n);link(v,i+n);lct[i+n].add_set_tag(read()); 119 } 120 q=read(); 121 int x,y,c; 122 while(q--){ 123 c=read();x=read();y=read(); 124 if(c==0) makeroot(x+n),access(x+n+lct)->add_set_tag(y); 125 else{ 126 if(x==y){puts("error");continue;} 127 makeroot(x);node*t=access(y+lct); 128 write(t->mx);PAU;write(t->mi);PAU;write(t->sm);ENT; 129 } 130 } 131 return 0; 132 }