bzoj1036
树链剖分模版吧。。。
1 #include<bits/stdc++.h> 2 #define l(a) ((a)<<1) 3 #define r(a) (((a)<<1)+1) 4 #define Rep(i,a) for(int i=0;i<e[a].size();i++) 5 #define rep(i,l,r) for(int i=l;i<r;i++) 6 #define lowbit(a) ((a)&(-(a))) 7 #define clr(a,x) memset(a,x,sizeof(a)) 8 typedef long long ll; 9 typedef unsigned long long ul; 10 using namespace std; 11 int read(){ 12 int ans=0,f=1; 13 char c=getchar(); 14 while(!isdigit(c)){ 15 if(c=='-') f=-1; 16 c=getchar(); 17 } 18 while(isdigit(c)){ 19 ans=ans*10+c-'0'; 20 c=getchar(); 21 } 22 return ans*f; 23 } 24 const int maxn=30050,inf=0x7fffffff; 25 int n,m,u,v,idcnt=0,id[maxn],idr[maxn],dep[maxn],w[maxn],f[maxn],top[maxn],size[maxn],son[maxn]; 26 vector<int>e[maxn]; 27 void dfs(int x){ 28 size[x]=1; 29 Rep(i,x){ 30 int to=e[x][i]; 31 if(to==f[x]) continue; 32 dep[to]=dep[x]+1; 33 f[to]=x; 34 dfs(to); 35 if(!son[x]||size[to]>size[son[x]]) son[x]=to; 36 size[x]+=size[to]; 37 } 38 } 39 int Top; 40 void Dfs(int x){ 41 id[x]=++idcnt; 42 idr[id[x]]=x; 43 top[x]=Top; 44 if(son[x]) Dfs(son[x]); 45 Rep(i,x) if(!id[e[x][i]]) Dfs(Top=e[x][i]); 46 } 47 struct node{ 48 int l,r,sum,mx; 49 }; 50 node x[maxn<<2]; 51 void maintain(int k){ 52 x[k].sum=x[l(k)].sum+x[r(k)].sum; 53 x[k].mx=max(x[l(k)].mx,x[r(k)].mx); 54 } 55 void update(int k){ 56 if(x[k].l==x[k].r){ 57 x[k].sum=x[k].mx=v; 58 return; 59 } 60 int mid=(x[k].l+x[k].r)>>1; 61 update(u<=mid?l(k):r(k)); 62 maintain(k); 63 } 64 int findmx(int k,int l,int r){ 65 if(x[k].l==l&&x[k].r==r) return x[k].mx; 66 int mid=(x[k].l+x[k].r)>>1; 67 if(l>mid) return findmx(r(k),l,r); 68 if(r<=mid) return findmx(l(k),l,r); 69 return max(findmx(l(k),l,mid),findmx(r(k),mid+1,r)); 70 } 71 int findsum(int k,int l,int r){ 72 if(x[k].l==l&&x[k].r==r) return x[k].sum; 73 int mid=(x[k].l+x[k].r)>>1; 74 if(l>mid) return findsum(r(k),l,r); 75 if(r<=mid) return findsum(l(k),l,r); 76 return findsum(l(k),l,mid)+findsum(r(k),mid+1,r); 77 } 78 int askmx(){ 79 int ans=-inf; 80 while(top[u]!=top[v]){ 81 if(dep[top[u]]<dep[top[v]]) swap(u,v); 82 ans=max(ans,findmx(1,id[top[u]],id[u])); 83 u=f[top[u]]; 84 } 85 if(dep[u]>dep[v]) swap(u,v); 86 ans=max(ans,findmx(1,id[u],id[v])); 87 return ans; 88 } 89 int asksum(){ 90 int ans=0; 91 while(top[u]!=top[v]){ 92 if(dep[top[u]]<dep[top[v]]) swap(u,v); 93 ans+=findsum(1,id[top[u]],id[u]); 94 u=f[top[u]]; 95 } 96 if(dep[u]>dep[v]) swap(u,v); 97 ans+=findsum(1,id[u],id[v]); 98 return ans; 99 } 100 void build(int k,int l,int r){ 101 x[k].l=l,x[k].r=r; 102 if(l==r){ 103 x[k].mx=x[k].sum=w[idr[l]]; 104 return; 105 } 106 int mid=(l+r)>>1; 107 build(l(k),l,mid); 108 build(r(k),mid+1,r); 109 maintain(k); 110 } 111 void init(){ 112 dep[1]=0; 113 dfs(1);Dfs(Top=1); 114 build(1,1,n); 115 } 116 int main() 117 { 118 n=read(); 119 rep(i,0,n-1){ 120 int from=read(),to=read(); 121 e[from].push_back(to); 122 e[to].push_back(from); 123 } 124 rep(i,1,n+1) w[i]=read(); 125 init(); 126 m=read(); 127 while(m--){ 128 char c[10]; 129 scanf(" %s",c); 130 u=read(),v=read(); 131 if(c[0]=='C'){ 132 u=id[u]; 133 update(1); 134 }else if(c[1]=='M'){ 135 printf("%d\n",askmx()); 136 }else{ 137 printf("%d\n",asksum()); 138 } 139 } 140 return 0; 141 }
1036: [ZJOI2008]树的统计Count
Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 8247 Solved: 3355
[Submit][Status][Discuss]
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本身
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