【BZOJ1036】 树的统计Count (树链剖分)
Description
一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w。我们将以下面的形式来要求你对这棵树完成
一些操作: I. CHANGE u t : 把结点u的权值改为t II. QMAX u v: 询问从点u到点v的路径上的节点的最大权值 I
II. 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”的形式给出。
对于100%的数据,保证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 4Sample Output
4
1
2
2
10
6
5
6
5
16
【题意】
给出一棵树,每个点有一个权值,要求三种操作:1.修改某个点的权值,2.询问x到y路径上各点的权值最大值,3.询问x到y路径上各点的权值之和。
【分析】
树链剖分+线段树维护。这题维护的是点的值。
代码如下:
1 #include<cstdio> 2 #include<cstdlib> 3 #include<cstring> 4 #include<iostream> 5 #include<algorithm> 6 using namespace std; 7 #define Maxn 30010 8 #define INF 0xfffffff 9 10 struct node 11 { 12 int x,y,next; 13 }t[2*Maxn];int len=0; 14 15 int first[Maxn],fa[Maxn],dep[Maxn],top[Maxn],w[Maxn],size[Maxn],son[Maxn]; 16 int wl=0; 17 18 struct nnode 19 { 20 int l,r,lc,rc,mx,sum; 21 }tr[2*Maxn];int tl=0; 22 23 int mymax(int x,int y) {return x>y?x:y;} 24 25 void ins(int x,int y) 26 { 27 t[++len].x=x;t[len].y=y; 28 t[len].next=first[x];first[x]=len; 29 } 30 31 void dfs1(int x,int f) 32 { 33 dep[x]=dep[f]+1; 34 size[x]=1;fa[x]=f;son[x]=0; 35 for(int i=first[x];i;i=t[i].next) if(t[i].y!=f) 36 { 37 dfs1(t[i].y,x); 38 size[x]+=size[t[i].y]; 39 if(size[t[i].y]>size[son[x]]) son[x]=t[i].y; 40 } 41 } 42 43 void dfs2(int x,int tp) 44 { 45 top[x]=tp;w[x]=++wl; 46 if(size[x]!=1) dfs2(son[x],tp); 47 for(int i=first[x];i;i=t[i].next) if(t[i].y!=fa[x]&&t[i].y!=son[x]) 48 { 49 dfs2(t[i].y,t[i].y); 50 } 51 } 52 53 int build(int l,int r) 54 { 55 int x=++tl; 56 tr[x].l=l;tr[x].r=r;tr[x].mx=-INF;tr[x].sum=0; 57 if(l!=r) 58 { 59 int mid=(l+r)>>1; 60 tr[x].lc=build(l,mid); 61 tr[x].rc=build(mid+1,r); 62 } 63 return x; 64 } 65 66 void change(int x,int y,int z) 67 { 68 if(tr[x].l==tr[x].r) 69 { 70 tr[x].mx=tr[x].sum=z; 71 return; 72 } 73 int mid=(tr[x].l+tr[x].r)>>1; 74 if(y<=mid) change(tr[x].lc,y,z); 75 else change(tr[x].rc,y,z); 76 tr[x].mx=mymax(tr[tr[x].lc].mx,tr[tr[x].rc].mx); 77 tr[x].sum=tr[tr[x].lc].sum+tr[tr[x].rc].sum; 78 } 79 80 int queryt(int x,int l,int r,bool p) 81 { 82 if(tr[x].l==l&&tr[x].r==r) 83 { 84 if(p) return tr[x].mx; 85 return tr[x].sum; 86 } 87 int mid=(tr[x].l+tr[x].r)>>1; 88 if(r<=mid) return queryt(tr[x].lc,l,r,p); 89 else if(l>mid) return queryt(tr[x].rc,l,r,p); 90 if(p) return mymax(queryt(tr[x].lc,l,mid,p),queryt(tr[x].rc,mid+1,r,p)); 91 return queryt(tr[x].lc,l,mid,p)+queryt(tr[x].rc,mid+1,r,p); 92 } 93 94 int query(int x,int y,bool p) 95 { 96 int f1=top[x],f2=top[y]; 97 int ans=0; 98 if(p) ans=-INF; 99 while(f1!=f2) 100 { 101 if(dep[f1]<dep[f2]) 102 { 103 swap(f1,f2); 104 swap(x,y); 105 } 106 if(p) ans=mymax(ans,queryt(1,w[f1],w[x],p)); 107 else ans+=queryt(1,w[f1],w[x],p); 108 x=fa[f1]; 109 f1=top[x]; 110 } 111 if(dep[x]<dep[y]) swap(x,y); 112 if(p) ans=mymax(ans,queryt(1,w[y],w[x],p)); 113 else ans+=queryt(1,w[y],w[x],p); 114 return ans; 115 } 116 117 int main() 118 { 119 int n; 120 scanf("%d",&n); 121 memset(first,0,sizeof(first)); 122 for(int i=1;i<n;i++) 123 { 124 int x,y; 125 scanf("%d%d",&x,&y); 126 ins(x,y);ins(y,x); 127 } 128 dep[0]=0;size[0]=0; 129 dfs1(1,0); 130 dfs2(1,1); 131 build(1,n); 132 for(int i=1;i<=n;i++) 133 { 134 int x; 135 scanf("%d",&x); 136 change(1,w[i],x); 137 } 138 int m; 139 char s[10]; 140 scanf("%d",&m); 141 while(m--) 142 { 143 int x,y; 144 scanf("%s%d%d",s,&x,&y); 145 if(s[0]=='C') 146 { 147 change(1,w[x],y); 148 } 149 else if(s[1]=='S') 150 { 151 printf("%d\n",query(x,y,0)); 152 } 153 else 154 { 155 printf("%d\n",query(x,y,1)); 156 } 157 } 158 return 0; 159 }
2016-05-10 16:54:19