树链剖分/线段树BZOJ1036-[ZJOI2008]树的统计Count

Posted Yiyi

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了树链剖分/线段树BZOJ1036-[ZJOI2008]树的统计Count相关的知识,希望对你有一定的参考价值。

【题目大意】

一棵树上有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本身

【思路】

我来兑现继续做ZJOI2008的flag了。裸的树链剖分,不说什么。但是!主意权值可以为负数,可以为负数!!所以初始化的时候max不是-1,而是要记得清成-INF。

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<algorithm>
  5 #include<vector>
  6 #define lson l,m,rt<<1
  7 #define rson m+1,r,rt<<1|1
  8 using namespace std;
  9 const int MAXN=30000+50;
 10 const int INF=0x7fffffff;
 11 vector<int> E[MAXN];
 12 int fa[MAXN],dep[MAXN],size[MAXN],son[MAXN];
 13 int top[MAXN],pos[MAXN];
 14 int w[MAXN];
 15 int cnt=0,n;
 16 int sum[MAXN<<2],maxn[MAXN<<2];
 17 char str[10];
 18 
 19 /*线段树部分*/
 20 void pushup(int rt)
 21 {
 22     sum[rt]=sum[rt<<1]+sum[rt<<1|1];
 23     maxn[rt]=max(maxn[rt<<1],maxn[rt<<1|1]);
 24 }
 25 
 26 void modify(int pos,int delta,int l,int r,int rt)
 27 {
 28     if (l==r)
 29     {
 30         sum[rt]=maxn[rt]=delta;
 31         return;
 32     }
 33     int m=(l+r)>>1;
 34     if (pos<=m) modify(pos,delta,lson);
 35     if (pos>m) modify(pos,delta,rson);
 36     pushup(rt);
 37 }
 38 
 39 int query(int sign,int L,int R,int l,int r,int rt)
 40 {
 41     if (L<=l && r<=R)
 42     {
 43         if (sign==1) return sum[rt];else return maxn[rt];
 44     }
 45     int m=(l+r)>>1;
 46     if (sign==1)
 47     {
 48         int ret=0;
 49         if (L<=m) ret+=query(sign,L,R,lson);
 50         if (R>m) ret+=query(sign,L,R,rson);
 51         return ret;
 52     }
 53     else
 54     {
 55         int res=-INF;
 56         if (L<=m) res=max(res,query(sign,L,R,lson));
 57         if (R>m) res=max(res,query(sign,L,R,rson));
 58         return res;
 59     }
 60 }
 61 
 62 /*树链剖分部分*/
 63 void addedge(int u,int v)
 64 {
 65     E[u].push_back(v);
 66     E[v].push_back(u);
 67 }
 68 
 69 void dfs1(int u,int pre,int d)
 70 {
 71     fa[u]=pre;
 72     dep[u]=d;
 73     size[u]=1;
 74     int tmpmax=0,hson=-1;
 75     for (int i=0;i<E[u].size();i++)
 76     {
 77         int to=E[u][i];
 78         if (to==pre) continue;
 79         dfs1(to,u,d+1);
 80         if (size[to]>tmpmax)
 81         {
 82             tmpmax=size[to];
 83             hson=to;
 84         }
 85         size[u]+=size[to];
 86     }
 87     son[u]=hson;
 88 }
 89 
 90 void dfs2(int u,int t)
 91 {
 92     pos[u]=++cnt;
 93     top[u]=t;
 94     if (son[u]==-1) return;
 95     dfs2(son[u],t);
 96     for (int i=0;i<E[u].size();i++)
 97         if (E[u][i]!=son[u] && E[u][i]!=fa[u]) dfs2(E[u][i],E[u][i]);
 98 }
 99 
100 int Que(int sign,int u,int v)
101 {
102     int ans;
103     if (sign==1) ans=0;else ans=-INF;
104     int f1=top[u],f2=top[v];
105     while (f1!=f2)
106     {
107         if (dep[f1]<dep[f2])
108         {
109             swap(f1,f2);
110             swap(u,v);
111         }
112         if (sign==1) ans+=query(1,pos[f1],pos[u],1,n,1);
113             else ans=max(ans,query(2,pos[f1],pos[u],1,n,1));
114         u=fa[f1];
115         f1=top[u];
116     }
117     if (dep[u]>dep[v]) swap(u,v);
118     if (sign==1) ans+=query(1,pos[u],pos[v],1,n,1);
119             else ans=max(ans,query(2,pos[u],pos[v],1,n,1));
120     return ans;
121 }
122 
123 /*主程序部分*/ 
124 void init()
125 {
126     scanf("%d",&n);
127     for (int i=0;i<n-1;i++)
128     {
129         int a,b;
130         scanf("%d%d",&a,&b);
131         addedge(a,b);
132     }
133     dfs1(1,0,1);
134     dfs2(1,1);
135 } 
136 
137 void get_ans()
138 {
139     for (int i=1;i<=n;i++) 
140     {
141         scanf("%d",&w[i]);
142         modify(pos[i],w[i],1,n,1);
143     }
144     int q;
145     scanf("%d",&q); 
146     for (int i=0;i<q;i++)
147     {
148         int u,v;
149         scanf("%s%d%d",str,&u,&v);
150         if (str[0]==C) modify(pos[u],v,1,n,1);
151         if (str[0]==Q && str[1]==S) cout<<Que(1,u,v)<<endl;
152         if (str[0]==Q && str[1]==M) cout<<Que(2,u,v)<<endl;
153     }
154 }
155 
156 int main()
157 {
158     init();
159     get_ans();
160     return 0;
161 }

 

以上是关于树链剖分/线段树BZOJ1036-[ZJOI2008]树的统计Count的主要内容,如果未能解决你的问题,请参考以下文章

bzoj1036: [ZJOI2008]树的统计Count(树链剖分+线段树维护)

树链剖分/线段树BZOJ1036-[ZJOI2008]树的统计Count

BZOJ 1036 [ZJOI2008]树的统计Count (树链剖分)(线段树单点修改)

bzoj1036 树的统计(树链剖分+线段树)

bzoj 1036 树链剖分+线段树 裸题

bzoj 1036 树的统计Count (树链剖分+线段树)