1. 程式人生 > >BZOJ1036: [ZJOI2008]樹的統計Count

BZOJ1036: [ZJOI2008]樹的統計Count

行為 == %d algorithm data style n) getch mes

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

Sample Output

4
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 }

BZOJ1036: [ZJOI2008]樹的統計Count