bzoj 1036 树的统计Count

题意:...

解法:树链剖分,对点进行重编号,这样的话线段树中点的信息就是树中点的信息。。。别的很常规。。。

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<algorithm>
  4 #define N 30010
  5 #define lson l,m,n<<1
  6 #define rson m+1,r,n<<1|1
  7 using namespace std;
  8 const int inf=1<<30;
  9 struct Edge{
 10     int u,v,next;
 11     Edge(){}
 12     Edge(int _u,int _v,int _next){
 13         u=_u;v=_v;next=_next;
 14     }
 15 }edge[N<<1];
 16 int head[N],cnt;
 17 int sz[N],top[N],fa[N],dep[N],hash[N],w[N],son[N],num;
 18 void init(){
 19     memset(head,-1,sizeof(head));
 20     cnt=num=0;
 21 }
 22 void add(int u,int v){
 23     edge[cnt]=Edge(u,v,head[u]);head[u]=cnt++;
 24     edge[cnt]=Edge(v,u,head[v]);head[v]=cnt++;
 25 }
 26 void dfs(int u,int d){
 27     sz[u]=1;son[u]=0;dep[u]=d;
 28     for(int k=head[u];k!=-1;k=edge[k].next){
 29         int v=edge[k].v;
 30         if(v==fa[u])continue;
 31         fa[v]=u;
 32         dfs(v,d+1);
 33         sz[u]+=sz[v];
 34         if(sz[v]>sz[son[u]])son[u]=v;
 35     }
 36 }
 37 void build_tree(int u,int pre){
 38     hash[u]=++num;top[u]=pre;
 39     if(son[u])build_tree(son[u],pre);
 40     for(int k=head[u];k!=-1;k=edge[k].next){
 41         int v=edge[k].v;
 42         if(v!=fa[u]&&v!=son[u])build_tree(v,v);
 43     }
 44 }
 45 struct segtree{
 46     int maxn[N<<2],sum[N<<2];
 47     void pushup(int n){
 48         sum[n]=sum[n<<1]+sum[n<<1|1];
 49         maxn[n]=max(maxn[n<<1],maxn[n<<1|1]);
 50     }
 51     void update(int nn,int x,int l,int r,int n){
 52         if(l==r){
 53             maxn[n]=sum[n]=x;
 54             return;
 55         }
 56         int m=(l+r)>>1;
 57         if(nn<=m)update(nn,x,lson);
 58         else update(nn,x,rson);
 59         pushup(n);
 60     }
 61     int query_max(int ll,int rr,int l,int r,int n){
 62         if(ll==l&&rr==r)return maxn[n];
 63         int m=(l+r)>>1;
 64         if(rr<=m)return query_max(ll,rr,lson);
 65         else if(ll>m)return query_max(ll,rr,rson);
 66         else return max(query_max(ll,m,lson),query_max(m+1,rr,rson));
 67     }
 68     int query_sum(int ll,int rr,int l,int r,int n){
 69         if(ll==l&&rr==r)return sum[n];
 70         int m=(l+r)>>1;
 71         if(rr<=m)return query_sum(ll,rr,lson);
 72         else if(ll>m)return query_sum(ll,rr,rson);
 73         else return query_sum(ll,m,lson)+query_sum(m+1,rr,rson);
 74     }
 75 }seg;
 76 int Query_max(int a,int b,int n){
 77     int ta=top[a],tb=top[b],ans=-inf;
 78     while(ta!=tb){
 79         if(dep[ta]<dep[tb]){
 80             swap(ta,tb);swap(a,b);
 81         }
 82         ans=max(ans,seg.query_max(hash[ta],hash[a],1,n,1));
 83         a=fa[ta];ta=top[a];
 84     }
 85     if(dep[a]>dep[b])swap(a,b);
 86     return max(ans,seg.query_max(hash[a],hash[b],1,n,1));
 87 }
 88 int Query_sum(int a,int b,int n){
 89     int ta=top[a],tb=top[b],ans=0;
 90     while(ta!=tb){
 91         if(dep[ta]<dep[tb]){
 92             swap(ta,tb);swap(a,b);
 93         }
 94         ans+=seg.query_sum(hash[ta],hash[a],1,n,1);
 95         a=fa[ta];ta=top[a];
 96     }
 97     if(dep[a]>dep[b])swap(a,b);
 98     return ans+seg.query_sum(hash[a],hash[b],1,n,1);
 99 }
100 int main(){
101     int n,a,b,q;
102     char op[10];
103     while(~scanf("%d",&n)){
104         init();
105         for(int i=1;i<n;i++){
106             scanf("%d%d",&a,&b);
107             add(a,b);
108         }
109         for(int i=1;i<=n;i++)scanf("%d",&w[i]);
110         dfs(1,1);
111         build_tree(1,1);
112         for(int i=1;i<=n;i++)seg.update(hash[i],w[i],1,n,1);
113         scanf("%d",&q);
114         while(q--){
115             scanf("%s%d%d",op,&a,&b);
116             if(strcmp(op,"QMAX")==0){
117                 int ans=Query_max(a,b,n);
118                 printf("%d\n",ans);
119             }else if(strcmp(op,"QSUM")==0){
120                 int ans=Query_sum(a,b,n);
121                 printf("%d\n",ans);
122             }else {
123                 seg.update(hash[a],b,1,n,1);
124             }
125         }
126     }
127     return 0;
128 }

 

 

posted @ 2013-02-09 00:14  silver__bullet  阅读(1100)  评论(0编辑  收藏  举报