BZOJ1036: [ZJOI2008]树的统计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 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
2
2
10
6
5
6
5
16
HINT
Source
树剖的模版题
1 #include<cstdio> 2 #include<cstdlib> 3 #include<algorithm> 4 #include<cstring> 5 #define MAXN 30005 6 using namespace std; 7 int fa[MAXN],dep[MAXN],size[MAXN],gs[MAXN]; 8 int top[MAXN],tree[MAXN],pre[MAXN],tot; 9 int first[MAXN],nxt[MAXN<<1],to[MAXN<<1],cnt; 10 int n; 11 int dat1[MAXN<<2],dat2[MAXN<<2],A[MAXN]; 12 int read(){ 13 int x=0,f=1;char ch=getchar(); 14 while(ch<'0'||ch>'9'){if('-'==ch)f=-1;ch=getchar();} 15 while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} 16 return x*f; 17 } 18 void add(int x,int y){ 19 nxt[++cnt]=first[x];first[x]=cnt;to[cnt]=y; 20 nxt[++cnt]=first[y];first[y]=cnt;to[cnt]=x; 21 } 22 void dfs1(int x){ 23 size[x]=1; 24 for(int e=first[x];e;e=nxt[e]){ 25 int y=to[e]; 26 if(y==fa[x]){ 27 continue; 28 } 29 fa[y]=x; 30 dep[y]=dep[x]+1; 31 dfs1(y); 32 size[x]+=size[y]; 33 if(size[y]>size[gs[x]]){ 34 gs[x]=y; 35 } 36 } 37 } 38 void dfs2(int x,int t){ 39 top[x]=t; 40 tree[x]=(++tot); 41 pre[tot]=x; 42 if(!gs[x]){ 43 return; 44 } 45 dfs2(gs[x],t); 46 for(int e=first[x];e;e=nxt[e]){ 47 int y=to[e]; 48 if(y==fa[x]||y==gs[x]){ 49 continue; 50 } 51 dfs2(y,y); 52 } 53 } 54 void pushup(int k){ 55 dat1[k]=dat1[k<<1]+dat1[k<<1|1]; 56 dat2[k]=max(dat2[k<<1],dat2[k<<1|1]); 57 } 58 void build(int k,int L,int R){ 59 if(L+1==R){ 60 dat1[k]=dat2[k]=A[pre[L]]; 61 return; 62 } 63 build(k<<1,L,(L+R)>>1); 64 build(k<<1|1,(L+R)>>1,R); 65 pushup(k); 66 } 67 void init(){ 68 n=read(); 69 for(int i=1;i<n;i++){ 70 int x=read(),y=read(); 71 add(x,y); 72 } 73 for(int i=1;i<=n;i++){ 74 A[i]=read(); 75 } 76 dfs1(1); 77 dfs2(1,1); 78 build(1,1,n+1); 79 } 80 void add(int a,int k,int L,int R,int x){ 81 if(L+1==R){ 82 dat1[k]=dat2[k]=x; 83 return; 84 } 85 int mid=((L+R)>>1); 86 if(a<mid){ 87 add(a,k<<1,L,mid,x); 88 } 89 else{ 90 add(a,k<<1|1,mid,R,x); 91 } 92 pushup(k); 93 } 94 int query_sum(int a,int b,int k,int L,int R){ 95 if(b<=L||R<=a){ 96 return 0; 97 } 98 else if(a<=L&&R<=b){ 99 return dat1[k]; 100 } 101 else{ 102 int lc=query_sum(a,b,k<<1,L,(L+R)>>1); 103 int rc=query_sum(a,b,k<<1|1,(L+R)>>1,R); 104 return (lc+rc); 105 } 106 } 107 int query_max(int a,int b,int k,int L,int R){ 108 if(b<=L||R<=a){ 109 return -1000000; 110 } 111 else if(a<=L&&R<=b){ 112 return dat2[k]; 113 } 114 else{ 115 int lc=query_max(a,b,k<<1,L,(L+R)>>1); 116 int rc=query_max(a,b,k<<1|1,(L+R)>>1,R); 117 return max(lc,rc); 118 } 119 } 120 int tree_ask_sum(int x,int y){ 121 int f1=top[x],f2=top[y]; 122 if(dep[f1]<dep[f2]){ 123 swap(f1,f2),swap(x,y); 124 } 125 int ret=0; 126 while(f1!=f2){ 127 ret+=query_sum(tree[f1],tree[x]+1,1,1,n+1); 128 x=fa[f1],f1=top[x]; 129 if(dep[f1]<dep[f2]){ 130 swap(f1,f2),swap(x,y); 131 } 132 } 133 if(dep[x]>dep[y]){ 134 swap(x,y); 135 } 136 ret+=query_sum(tree[x],tree[y]+1,1,1,n+1); 137 return ret; 138 } 139 int tree_ask_max(int x,int y){ 140 int f1=top[x],f2=top[y]; 141 if(dep[f1]<dep[f2]){ 142 swap(f1,f2),swap(x,y); 143 } 144 int ret=-1000000; 145 while(f1!=f2){ 146 ret=max(ret,query_max(tree[f1],tree[x]+1,1,1,n+1)); 147 x=fa[f1],f1=top[x]; 148 if(dep[f1]<dep[f2]){ 149 swap(f1,f2),swap(x,y); 150 } 151 } 152 if(dep[x]>dep[y]){ 153 swap(x,y); 154 } 155 ret=max(ret,query_max(tree[x],tree[y]+1,1,1,n+1)); 156 return ret; 157 } 158 void solve(){ 159 int T=read(); 160 for(int i=1;i<=T;i++){ 161 char ch[10]; 162 scanf("%s",ch); 163 int x=read(),y=read(); 164 if('M'==ch[1]){ 165 printf("%d\n",tree_ask_max(x,y)); 166 } 167 else if('S'==ch[1]){ 168 printf("%d\n",tree_ask_sum(x,y)); 169 } 170 else{ 171 add(tree[x],1,1,n+1,y); 172 } 173 } 174 } 175 int main() 176 { 177 // freopen("data.in","r",stdin); 178 init(); 179 solve(); 180 return 0; 181 }