【BZOJ】【P3720】【Gty的妹子树】【题解】【分块】

来源:互联网 发布:苹果5怎么用3g网络 编辑:程序博客网 时间:2024/05/01 13:26

传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=3720

一看数据范围就知道要分块

分完块然后就是排序,加点的时候可以动态分裂出来一个个块,但蒟蒻懒得写……

修改查询都是sqrt(n)logn的

Code:

#include<bits/stdc++.h>using namespace std;const int maxn=60010;int sqrtn,siz[maxn],dep[maxn],bel[maxn],cnt,fa[maxn],n,lastans,w[maxn],mp[maxn],Bfa[maxn],m;vector<int>G[maxn],Ge[maxn];vector<int>block[maxn];int ind[maxn],vis[maxn];void dfs(int u){for(int i=0;i<G[u].size();i++){int v=G[u][i];if(v==fa[u])continue;fa[v]=u;dep[v]=dep[u]+1;if(siz[bel[u]]<sqrtn)siz[bel[v]=bel[u]]++;elseGe[bel[u]].push_back(bel[v]),Ge[bel[v]].push_back(bel[u]);dfs(v);}}int op0(int u,int x){int ans=0;if(bel[u]==u){ans+=block[u].end()-upper_bound(block[u].begin(),block[u].end(),x);for(int i=0;i<Ge[u].size();i++){int v=Ge[u][i]; if(dep[v]>dep[u]){ans+=op0(Ge[u][i],x);}}return ans;}else{ans+=w[u]>x;for(int i=0;i<G[u].size();i++){int v=G[u][i];if(v==fa[u])continue;ans+=op0(v,x);}return ans;}}void op1(int u,int x){int pos=lower_bound(block[bel[u]].begin(),block[bel[u]].end(),w[u])-block[bel[u]].begin();block[bel[u]][pos]=x;w[u]=x;sort(block[bel[u]].begin(),block[bel[u]].end());}void op2(int u,int x){fa[++n]=u;w[n]=x;dep[n]=dep[u]+1;G[u].push_back(n);G[n].push_back(u);block[bel[n]=bel[u]].push_back(x);sort(block[bel[u]].begin(),block[bel[u]].end());}int main(){scanf("%d",&n);sqrtn=sqrt(n);for(int i=1;i<n;i++){int u,v;scanf("%d%d",&u,&v);G[u].push_back(v);G[v].push_back(u);}for(int i=1;i<=n;i++)bel[i]=i,siz[i]=1,scanf("%d",&w[i]);dfs(1);for(int i=1;i<=n;i++){block[bel[i]].push_back(w[i]);if(!vis[bel[i]])vis[bel[i]]=1,ind[++ind[0]]=bel[i];}for(int i=1;i<=ind[0];i++)sort(block[ind[i]].begin(),block[ind[i]].end());scanf("%d",&m);while(m--){int op;scanf("%d",&op);int u,x;scanf("%d%d",&u,&x);u^=lastans;x^=lastans;if(op==0){printf("%d\n",(lastans=op0(u,x)));}else if(op==1){op1(u,x);}elseif(op==2){op2(u,x);}}return 0;}


0 0
原创粉丝点击