码迷,mamicode.com
首页 > 其他好文 > 详细

BZOJ3531 SDOI2014 旅行 - 树链剖分,主席树

时间:2018-03-01 23:42:25      阅读:310      评论:0      收藏:0      [点我收藏+]

标签:eof   类型   class   +=   turn   void   div   init   代码   

题意:给定一棵树,树上每个点有权值和类型。支持:修改某个点的类型;修改某个点的权值;询问某条链上某个类型的点的和/最大值。点数/类型数/询问数<=100000.

分析:

树链剖分,对每个类型的点建立线段树(动态开点)。

 

note: 忘记写t_query返回值调半天…… 

莫名其妙地1A

代码:

  1 #include <bits/stdc++.h>
  2 using namespace std;
  3 
  4 int a[5000005],s[5000005],dep[100005],size[100005],vis[100005],top[100005],wson[100005],fa[100005][20],n,m,t1,t2,t3,t4;
  5 int sid[100005],tid[100005],ind,cnt,ch[5000005][2],root[100005],c[100005],w[100005];
  6 vector <int> g[100005];
  7 
  8 void dfs1(int p){
  9     size[p]=1;
 10     vis[p]=1;
 11     for(int i=0;i<g[p].size();i++)
 12         if(vis[g[p][i]]==0)  {
 13             dep[g[p][i]]=dep[p]+1;
 14             fa[g[p][i]][0]=p;
 15             dfs1(g[p][i]);
 16             size[p]+=size[g[p][i]];
 17             if(size[g[p][i]]>size[wson[p]]) wson[p]=g[p][i];
 18         }
 19 }
 20 
 21 void dfs2(int p){
 22     vis[p]=1;
 23     sid[p]=++ind;
 24     tid[ind]=p;
 25     if(wson[p]) {
 26         top[wson[p]]=top[p];
 27         dfs2(wson[p]);
 28     }
 29     for(int i=0;i<g[p].size();i++)
 30         if(vis[g[p][i]]==0) {
 31             top[g[p][i]]=g[p][i];
 32             dfs2(g[p][i]);
 33         }
 34 }
 35 
 36 void lca_presolve() {
 37     for(int i=1;i<=17;i++) 
 38         for(int j=1;j<=n;j++)
 39             fa[j][i]=fa[fa[j][i-1]][i-1];
 40 }
 41 
 42 int lca(int p,int q) {
 43     if(dep[q]>dep[p]) swap(p,q);
 44     for(int i=17;i>=0;i--) if(dep[fa[p][i]]>=dep[q]) p=fa[p][i];
 45     for(int i=17;i>=0;i--) if(fa[p][i]-fa[q][i]) p=fa[p][i],q=fa[q][i];
 46     if(p-q) p=fa[p][0],q=fa[q][0];
 47     return max(p,q);
 48 }
 49 
 50 void init() {
 51     dep[1]=1;
 52     top[1]=1; 
 53     dfs1(1);
 54     memset(vis,0,sizeof vis);
 55     dfs2(1);
 56     lca_presolve();
 57 }
 58 
 59 void modify(int &p,int l,int r,int pos,int k) {
 60     if(p==0) p=++cnt;
 61     if(l==r) {
 62         a[p]=k;
 63         s[p]=k;
 64     }
 65     else {
 66         if(pos<=(l+r)/2) modify(ch[p][0],l,(l+r)/2,pos,k);
 67         else modify(ch[p][1],(l+r)/2+1,r,pos,k);
 68         a[p]=max(a[ch[p][0]],a[ch[p][1]]);
 69         s[p]=s[ch[p][0]]+s[ch[p][1]];
 70     }
 71 }
 72 
 73 void tmodify(int t,int pos,int k) {
 74     modify(root[t],1,2*n,sid[pos],k);
 75 }
 76 
 77 int queryMax(int p,int l,int r,int ql,int qr) {
 78     if(p==0) return 0;
 79     if(l>qr||r<ql) return 0;
 80     if(l>=ql&&r<=qr) return a[p];
 81     return max(queryMax(ch[p][0],l,(l+r)/2,ql,qr),queryMax(ch[p][1],(l+r)/2+1,r,ql,qr));
 82 }
 83 
 84 int querySum(int p,int l,int r,int ql,int qr) {
 85     if(p==0) return 0;
 86     if(l>qr||r<ql) return 0;
 87     if(l>=ql&&r<=qr) return s[p];
 88     return querySum(ch[p][0],l,(l+r)/2,ql,qr)+querySum(ch[p][1],(l+r)/2+1,r,ql,qr);
 89 }
 90 
 91 int lqueryMax(int t,int anc,int son) {
 92     int ans=0;
 93     while(dep[top[son]]>dep[anc]) {
 94         ans=max(ans,queryMax(root[t],1,2*n,sid[top[son]],sid[son]));
 95         son=fa[top[son]][0];
 96     }
 97     ans=max(ans,queryMax(root[t],1,2*n,sid[anc],sid[son]));
 98     return ans;
 99 }
100 
101 int lquerySum(int t,int anc,int son) {
102     int ans=0;
103     while(dep[top[son]]>dep[anc]) {
104         ans+=querySum(root[t],1,2*n,sid[top[son]],sid[son]);
105         son=fa[top[son]][0];
106     }
107     ans+=querySum(root[t],1,2*n,sid[anc],sid[son]);
108     return ans;
109 }
110 
111 int tqueryMax(int t,int p,int q) {
112     int l=lca(p,q);
113     return max(lqueryMax(t,l,p),lqueryMax(t,l,q));
114 }
115 
116 int tquerySum(int t,int p,int q) {
117     int l=lca(p,q);
118     return lquerySum(t,l,p)+lquerySum(t,l,q)-w[l]*(c[l]==c[p]);
119 }
120 
121 string str;
122 
123 int main(){
124     ios::sync_with_stdio(false);
125     cin>>n>>m;
126     for(int i=1;i<=n;i++) {
127         cin>>t1>>t2;
128         //tmodify(t2,sid[i],t1);
129         c[i]=t2;
130         w[i]=t1;
131     }
132     for(int i=1;i<n;i++)  {
133         cin>>t1>>t2;
134         g[t1].push_back(t2);
135         g[t2].push_back(t1);
136     }
137     init();
138     for(int i=1;i<=n;i++) {
139         tmodify(c[i],i,w[i]);    
140     }
141     for(int i=1;i<=m;i++) {
142         cin>>str>>t1>>t2;
143         if(str=="CC") {
144             tmodify(c[t1],t1,0);
145             tmodify(t2,t1,w[t1]);
146             c[t1]=t2;
147         }
148         if(str=="CW") {
149             tmodify(c[t1],t1,0);
150             tmodify(c[t1],t1,t2);
151             w[t1]=t2;
152         }
153         if(str=="QS") {
154             cout<<tquerySum(c[t1],t1,t2)<<endl;
155         }
156         if(str=="QM") {
157             cout<<tqueryMax(c[t1],t1,t2)<<endl;
158         }
159     }
160 } 

 

BZOJ3531 SDOI2014 旅行 - 树链剖分,主席树

标签:eof   类型   class   +=   turn   void   div   init   代码   

原文地址:https://www.cnblogs.com/mollnn/p/8490666.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!