首页 > 代码库 > 【块状树】bzoj3731 Gty的超级妹子树
【块状树】bzoj3731 Gty的超级妹子树
带 加点 删边的块状树。
加点在 bzoj3720 说过。
删边其实就是块顶打标记,记录其属于哪棵树,防止在dfs搜集答案时跑到别的树上。
然后暴力把所在块拆开。
好像用邻接表存图,直接在vector里删边也行?
1 #include<cstdio> 2 #include<algorithm> 3 #include<cmath> 4 #include<vector> 5 using namespace std; 6 #define maxn 200001 7 int Res,Num;char C,CH[20]; 8 inline int Ge() 9 { 10 Res=0;C=‘*‘; 11 while(C<‘0‘||C>‘9‘)C=getchar(); 12 while(C>=‘0‘&&C<=‘9‘){Res=Res*10+(C-‘0‘);C=getchar();} 13 return Res; 14 } 15 inline void P(int x) 16 { 17 Num=0;if(!x){putchar(‘0‘);puts("");return;} 18 while(x>0)CH[++Num]=x%10,x/=10; 19 while(Num)putchar(CH[Num--]+48); 20 putchar(‘\n‘); 21 } 22 typedef vector<int>::iterator ITER; 23 vector<int>List[maxn],Goto[maxn]; 24 struct Graph 25 { 26 int v[maxn<<1],first[maxn<<1],next[maxn<<1],en; 27 void AddEdge(const int &a,const int &b) 28 {v[++en]=b;next[en]=first[a];first[a]=en;} 29 }; 30 Graph G,son; 31 int top[maxn],siz[maxn],sz,w[maxn],belong_tree[maxn]; 32 bool vis[maxn],root[maxn]; 33 int n,x,y,m,op,tree_num; 34 int ans,val,U; 35 void makeblock(int cur) 36 { 37 vis[cur]=true; 38 for(int i=G.first[cur];i;i=G.next[i]) 39 if(!vis[G.v[i]]) 40 { 41 son.AddEdge(cur,G.v[i]); 42 if(siz[top[cur]]<sz) 43 { 44 List[top[cur]].push_back(w[G.v[i]]); 45 siz[top[cur]]++; 46 top[G.v[i]]=top[cur]; 47 } 48 makeblock(G.v[i]); 49 } 50 } 51 void makeGoto(int cur) 52 { 53 for(int i=son.first[cur];i;i=son.next[i]) 54 { 55 if(top[son.v[i]]!=top[cur]) 56 Goto[top[cur]].push_back(son.v[i]); 57 makeGoto(son.v[i]); 58 } 59 } 60 void dfs(int cur)//在Goto树上询问 61 { 62 ans+=( List[cur].end() - upper_bound( List[cur].begin() , List[cur].end() , val ) ); 63 for(ITER it=Goto[cur].begin();it!=Goto[cur].end();it++) 64 if(belong_tree[*it]==belong_tree[cur])//通过标记控制在一棵树内 65 dfs(*it); 66 } 67 void dfs_block(int cur)//在块内询问 68 { 69 if(w[cur]>val) ans++; 70 for(int i=son.first[cur];i;i=son.next[i]) 71 if(top[son.v[i]]==top[cur]) dfs_block(son.v[i]); 72 else if(belong_tree[son.v[i]]==belong_tree[top[cur]]) dfs(son.v[i]); 73 } 74 void query() 75 { 76 ans=0; 77 if(U==top[U]) dfs(U); 78 else dfs_block(U); 79 P(ans); 80 } 81 void update() 82 { 83 List[top[U]].erase( lower_bound(List[top[U]].begin(),List[top[U]].end(),w[U]) ); 84 w[U]=val; 85 List[top[U]].insert( lower_bound(List[top[U]].begin(),List[top[U]].end(),val+1) , val ); 86 } 87 void AddPoint() 88 { 89 n++; 90 if(siz[top[U]]<sz) 91 { 92 top[n]=top[U]; 93 siz[top[n]]++; 94 } 95 else 96 { 97 top[n]=n; 98 siz[n]++; 99 Goto[top[U]].push_back(n);100 belong_tree[n]=belong_tree[top[U]];101 }102 son.AddEdge(U,n);103 w[n]=val;104 List[top[n]].insert( lower_bound(List[top[n]].begin(),List[top[n]].end(),val+1) , val );105 }106 void dfs_split(int cur)//设置每个块顶属于哪个树的标记 107 {108 for(ITER it=Goto[cur].begin();it!=Goto[cur].end();it++)109 if(belong_tree[cur]==belong_tree[*it])110 dfs_split(*it);111 belong_tree[cur]=tree_num;112 }113 void dfs_split_block(int cur)//把分裂的块的下半部分重构块 114 {115 List[U].push_back(w[cur]);116 for(int i=son.first[cur];i;i=son.next[i])117 {118 if(top[son.v[i]]==top[cur])119 dfs_split_block(son.v[i]);120 else if(belong_tree[son.v[i]]==belong_tree[top[U]])//顺手设置它下面的块的标记 121 {122 Goto[U].push_back(son.v[i]);123 dfs_split(son.v[i]);124 }125 siz[U]++;126 }127 top[cur]=U;128 }129 void dfs_remain_block(int cur)//把分裂的块的上半部分重构块 130 {131 List[top[U]].push_back(w[cur]); siz[top[U]]++;132 for(int i=son.first[cur];i;i=son.next[i])133 if( (!root[son.v[i]]) && (top[son.v[i]]==top[cur]) )134 dfs_remain_block(son.v[i]);135 }136 void Delete_Edge()137 {138 root[U]=true;139 tree_num++;140 if(U!=top[U])141 {142 List[top[U]].clear();siz[top[U]]=0;143 dfs_remain_block(top[U]);144 sort(List[top[U]].begin(),List[top[U]].end());//重构分裂的块的上半部分145 dfs_split_block(U);146 belong_tree[U]=tree_num;147 sort(List[U].begin(),List[U].end());//重构分裂的块的下半部分 148 }149 else150 dfs_split(U);151 }152 int main()153 {154 n=Ge();155 for(int i=1;i<n;i++)156 {157 x=Ge();y=Ge();158 G.AddEdge(x,y);159 G.AddEdge(y,x);160 }161 sz=sqrt((double)n*log2(n));162 for(int i=1;i<=n;i++)163 {164 w[i]=Ge();165 top[i]=i;166 siz[i]=1;167 }168 makeblock(1);169 for(int i=1;i<=n;i++)170 if(top[i]==i)171 {172 List[i].push_back(w[i]);173 sort(List[i].begin(),List[i].end());174 }175 makeGoto(1);176 root[1]=true;177 m=Ge();178 for(int i=1;i<=m;i++)179 {180 op=Ge();U=Ge();U^=ans;181 if(!op){val=Ge();val^=ans;query();}182 else if(op==1){val=Ge();val^=ans;update();}183 else if(op==2){val=Ge();val^=ans;AddPoint();}184 else Delete_Edge();185 }186 return 0;187 }
【块状树】bzoj3731 Gty的超级妹子树
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。