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 }
View Code

1036: [ZJOI2008]树的统计Count

Time Limit: 10 Sec  Memory Limit: 162 MB
Submit: 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

Sample Output

4
1
2
2
10
6
5
6
5
16

HINT

 

Source

[Submit][Status][Discuss]
posted @ 2015-08-02 22:00  ChenThree  阅读(163)  评论(0编辑  收藏  举报