bzoj1036:[Zjoi2008]树的统计
Description
一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w。
我们将以下面的形式来要求你对这棵树完成一些操作:
I. CHANGE u t : 把结点u的权值改为t
II. QMAX u v: 询问从点u到点v的路径上的节点的最大权值
III. QSUM u v: 询问从点u到点v的路径上的节点的权值和
注意:从点u到点v的路径上的节点包括u和v本身
我们将以下面的形式来要求你对这棵树完成一些操作:
I. CHANGE u t : 把结点u的权值改为t
II. QMAX u v: 询问从点u到点v的路径上的节点的最大权值
III. QSUM u v: 询问从点u到点v的路径上的节点的权值和
注意:从点u到点v的路径上的节点包括u和v本身
Input
输入文件的第一行为一个整数n,表示节点的个数。
接下来n – 1行,每行2个整数a和b,表示节点a和节点b之间有一条边相连。
接下来n行,每行一个整数,第i行的整数wi表示节点i的权值。
接下来1行,为一个整数q,表示操作的总数。
接下来q行,每行一个操作,以“CHANGE u t”或者“QMAX u v”或者“QSUM u v”的形式给出。
保证1<=n<=30000,0<=q<=200000;中途操作中保证每个节点的权值w在-30000到30000之间。
接下来n – 1行,每行2个整数a和b,表示节点a和节点b之间有一条边相连。
接下来n行,每行一个整数,第i行的整数wi表示节点i的权值。
接下来1行,为一个整数q,表示操作的总数。
接下来q行,每行一个操作,以“CHANGE u t”或者“QMAX u v”或者“QSUM u v”的形式给出。
保证1<=n<=30000,0<=q<=200000;中途操作中保证每个节点的权值w在-30000到30000之间。
Output
对于每个“QMAX”或者“QSUM”的操作,每行输出一个整数表示要求输出的结果。
Sample Input
4
1 2
2 3
4 1
4 2 1 3
12
QMAX 3 4
QMAX 3 3
QMAX 3 2
QMAX 2 3
QSUM 3 4
QSUM 2 1
CHANGE 1 5
QMAX 3 4
CHANGE 3 6
QMAX 3 4
QMAX 2 4
QSUM 3 4
Sample Output
4
1
2
2
10
6
5
6
5
16
现在很晚了,这种板子题我也不知道怎么表述。
到时候再补吧,先丢代码
1 #include<cstdio> 2 #include<algorithm> 3 using namespace std; 4 const int N=60001; 5 int n,m,cnt,now,son[N],f[N],nex[N],h[N],top[N],id[N],size[N],dep[N],ans,mxx; 6 struct oo{int a,b,v,sum,mx;}s[N*2-20000]; 7 void ins(int x,int y) 8 { 9 son[++cnt]=y; 10 nex[cnt]=h[x]; 11 h[x]=cnt; 12 } 13 void dfs(int x) 14 { 15 size[x]=1; 16 for(int i=h[x];i;i=nex[i]) 17 { 18 int v=son[i]; 19 if(v==f[x])continue; 20 dep[v]=dep[x]+1; 21 f[v]=x; 22 dfs(v); 23 size[x]+=size[v]; 24 } 25 } 26 void dfs2(int x,int y) 27 { 28 int k=0; 29 id[x]=++now;top[x]=y; 30 for(int i=h[x];i;i=nex[i]) 31 if(dep[son[i]]>dep[x]&&size[son[i]]>size[k]) 32 k=son[i]; 33 if(k==0)return ; 34 dfs2(k,y); 35 for(int i=h[x];i;i=nex[i]) 36 { 37 if(son[i]==k)continue; 38 if(dep[son[i]]>dep[x]) 39 dfs2(son[i],son[i]); 40 } 41 } 42 void build(int x,int l,int r) 43 { 44 s[x].a=l,s[x].b=r; 45 if(l==r){s[x].mx=-9999999;return ;} 46 build(x<<1,l,l+r>>1); 47 build(x<<1|1,(l+r>>1)+1,r); 48 } 49 void change(int x,int l,int v) 50 { 51 if(s[x].a==s[x].b){s[x].v=v;s[x].sum=v;s[x].mx=v;return ;} 52 int mid=s[x].a+s[x].b>>1; 53 if(l<=mid)change(x<<1,l,v); 54 else change(x<<1|1,l,v); 55 s[x].mx=max(s[x<<1].mx,s[x<<1|1].mx); 56 s[x].sum=s[x<<1].sum+s[x<<1|1].sum; 57 } 58 void get(int x,int l,int r) 59 { 60 if(l<=s[x].a&&r>=s[x].b) 61 ans+=s[x].sum,mxx=max(mxx,s[x].mx); 62 else 63 { 64 int mid=s[x].a+s[x].b>>1; 65 if(l<=mid)get(x<<1,l,r); 66 if(r>mid)get(x<<1|1,l,r); 67 } 68 } 69 void qmax(int x,int y) 70 { 71 int mx=-99999999; 72 while(top[x]!=top[y]) 73 { 74 if(dep[top[x]]<dep[top[y]])swap(x,y); 75 mxx=-99999999;ans=0; 76 get(1,id[top[x]],id[x]); 77 mx=max(mx,mxx); 78 x=f[top[x]]; 79 } 80 if(id[x]>id[y])swap(x,y); 81 mxx=-99999999;ans=0; 82 get(1,id[x],id[y]); 83 mx=max(mx,mxx); 84 printf("%d\n",mx); 85 } 86 void qsum(int x,int y) 87 { 88 int sum=0; 89 while(top[x]!=top[y]) 90 { 91 if(dep[top[x]]<dep[top[y]])swap(x,y); 92 ans=0; 93 get(1,id[top[x]],id[x]); 94 sum+=ans; 95 x=f[top[x]]; 96 } 97 if(id[x]>id[y])swap(x,y); 98 ans=0; 99 get(1,id[x],id[y]); 100 sum+=ans; 101 printf("%d\n",sum); 102 } 103 int main() 104 { 105 scanf("%d",&n); 106 for(int i=1,x,y;i<n;i++) 107 scanf("%d%d",&x,&y),ins(x,y),ins(y,x); 108 dfs(1),dfs2(1,1);build(1,1,n); 109 for(int i=1,x;i<=n;i++) 110 scanf("%d",&x),change(1,id[i],x); 111 scanf("%d",&m);char p[13];int a,b; 112 while(m--) 113 { 114 scanf("%s",p+1); 115 if(p[2]=='S') 116 { 117 scanf("%d%d",&a,&b); 118 qsum(a,b); 119 } 120 if(p[2]=='M') 121 { 122 scanf("%d%d",&a,&b); 123 qmax(a,b); 124 } 125 if(p[2]=='H') 126 { 127 scanf("%d%d",&a,&b); 128 change(1,id[a],b); 129 } 130 } 131 }