BZOJ[1036] [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
树链剖分模板题
1 #include<iostream> 2 #include<cstring> 3 #include<cstdio> 4 #include<cstdlib> 5 #include<cmath> 6 #include<algorithm> 7 using namespace std; 8 int son[30001],fa[30001],v[30001],deep[30001],num[30001]; 9 int d[30001],t[30001],fd[30001]; 10 int s; 11 struct data 12 { 13 int to,next; 14 }a[60001]; 15 int head[30001]; 16 int cnt=0; 17 void add(int u,int v){a[cnt].to=v;a[cnt].next=head[u];head[u]=cnt;cnt++;} 18 int n; 19 void dfs(int now,int f,int de) 20 { 21 fa[now]=f; 22 deep[now]=de; 23 num[now]=1; 24 for(int i=head[now];i>=0;i=a[i].next) 25 { 26 if(a[i].to!=f) 27 { 28 dfs(a[i].to,now,de+1); 29 num[now]+=num[a[i].to]; 30 if(num[a[i].to]>num[son[now]]) son[now]=a[i].to; 31 } 32 } 33 } 34 void dfs1(int now,int f,int tp) 35 { 36 t[now]=tp; 37 d[now]=++s; 38 fd[s]=now; 39 if(son[now]) dfs1(son[now],now,tp); 40 for(int i=head[now];i>=0;i=a[i].next) 41 { 42 int v=a[i].to; 43 if(v!=son[now]&&v!=f) dfs1(v,now,v); 44 } 45 } 46 int maxn[90005],sum[90005]; 47 void pushup(int l,int r,int o) 48 { 49 int lo=o<<1,ro=lo+1; 50 maxn[o]=max(maxn[lo],maxn[ro]); 51 sum[o]=sum[lo]+sum[ro]; 52 } 53 void build(int l,int r,int o) 54 { 55 if(l==r)maxn[o]=sum[o]=v[fd[l]]; 56 else 57 { 58 int mid=(l+r)>>1,lo=o<<1,ro=lo+1; 59 build(l,mid,lo); 60 build(mid+1,r,ro); 61 pushup(l,r,o); 62 } 63 } 64 65 void updata(int l,int r,int o,int m,int va) 66 { 67 if(l==m&&r==m) maxn[o]=sum[o]=va; 68 else 69 { 70 int mid=(l+r)>>1,lo=o<<1,ro=lo+1; 71 if(m>mid) updata(mid+1,r,ro,m,va); 72 else updata(l,mid,lo,m,va); 73 pushup(l,r,o); 74 } 75 } 76 int al,ar,Max=-2147483647,Sum=0; 77 void query(int l,int r,int o) 78 { 79 if(l>=al&&r<=ar) 80 { 81 Max=max(Max,maxn[o]); 82 Sum+=sum[o]; 83 } 84 else 85 { 86 int mid=(l+r)>>1,lo=o<<1,ro=lo+1; 87 if(ar>mid) query(mid+1,r,ro); 88 if(al<=mid) query(l,mid,lo); 89 } 90 } 91 char ch[20]; 92 void find(int x,int y) 93 { 94 Max=-2147483647,Sum=0; 95 int f1=t[x],f2=t[y]; 96 while(f1!=f2) 97 { 98 if(deep[f1]<deep[f2]) 99 { 100 swap(f1,f2); 101 swap(x,y); 102 } 103 al=d[f1],ar=d[x]; 104 query(1,n,1); 105 x=fa[f1]; 106 f1=t[x]; 107 } 108 if(deep[x]>deep[y]) swap(x,y); 109 al=d[x],ar=d[y]; 110 query(1,n,1); 111 if(ch[1]=='M') printf("%d\n",Max); 112 else printf("%d\n",Sum); 113 } 114 int main() 115 { 116 memset(head,-1,sizeof(head)); 117 scanf("%d",&n); 118 for(int i=1;i<n;i++) 119 { 120 int u1,v1; 121 scanf("%d%d",&u1,&v1); 122 add(u1,v1); 123 add(v1,u1); 124 } 125 for(int i=1;i<=n;i++) scanf("%d",&v[i]); 126 dfs(1,0,1); 127 dfs1(1,0,1); 128 build(1,n,1); 129 int q; 130 scanf("%d",&q); 131 for(int i=1;i<=q;i++) 132 { 133 134 scanf("%s",ch); 135 int x,y; 136 if(ch[0]=='C') 137 { 138 scanf("%d%d",&x,&y); 139 updata(1,n,1,d[x],y); 140 } 141 else 142 { 143 scanf("%d%d",&x,&y); 144 find(x,y); 145 } 146 } 147 //system("pause"); 148 }
O(∩_∩)O~ (*^__^*) 嘻嘻…… O(∩_∩)O哈哈~