bzoj3720: Gty的妹子树
来源:互联网 发布:商务软件解决方案比赛 编辑:程序博客网 时间:2024/05/01 05:31
题目链接
bzoj3720
题意
维护一棵初始有n个节点的有根树(根节点为1),树上节点编号为1-n,每个点有一个权值wi。
支持以下操作:
0 u x 询问以u为根的子树中,严格大于x的值的个数。(u^=lastans,x^=lastans)
1 u x 把u节点的权值改成x。(u^=lastans,x^=lastans)
2 u x 添加一个编号为”当前树中节点数+1”的节点,其父节点为u,其权值为x。(u^=lastans,x^=lastans)
最开始时lastans=0。(强制在线)
(1<=n<=30000,1<=m<=30000)
题解
与子树相关的问题我们能想到树剖,dfs序等东西。但是这道题要支持加点与大于x数的个数的统计。这样就不是很好做了。
但是注意到修改是单点的,并且n不是非常大。我们可以分块乱搞。
我们先确定一个块的大小S,将树分成若干个联通块,每块的大小都不超过S。
我们在每个块内将权值从小到大排序。
询问时,若在一个整块内,我们二分查找,否则暴力。
修改是暴力维护块内的权值有序。
加点时判断父亲所在块大小是否等于S,等于的话该点单独成一块,否则加入父亲所在块内,注意也要维护块内权值有序。
由于有二分操作,块的大小取
代码:
#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>#include<queue>#include<vector>#include<cmath>using namespace std;#define N 60010#define M 60010struct node{ int pos,top,data,fa;}t[N];struct block{ int size; vector<int>v;}b[M];struct edge{ int x,next;}e[N*2][2];int x,y,n,m,tot[2],num,first[N][2],ans,lim,op;queue<int>q;void add(int x,int y,int k){ e[++tot[k]][k].x=y; e[tot[k]][k].next=first[x][k]; first[x][k]=tot[k];}void newnode(int x,int top,int pos){ b[pos].v.push_back(t[x].data); b[pos].size++; t[x].pos=pos; t[x].top=top;}void bfs(){ newnode(1,1,++num); q.push(1); while(!q.empty()){ x=q.front(); q.pop(); for(int i=first[x][0];i;i=e[i][0].next) if(e[i][0].x!=t[x].fa){ if(b[t[x].pos].size>=lim){ newnode(e[i][0].x,e[i][0].x,++num); add(t[x].pos,num,1); }else newnode(e[i][0].x,t[x].top,t[x].pos); t[e[i][0].x].fa=x; q.push(e[i][0].x); } }}int count(int x,int y){ int l=0,r=b[x].v.size(),mid; while((r-l)>1){ mid=(l+r)>>1; if(b[x].v[mid]>y)r=mid; else l=mid; } if(b[x].v[l]>y)r=l; int tmp=b[x].v.size()-r; for(int i=first[x][1];i;i=e[i][1].next) tmp+=count(e[i][1].x,y); return tmp;}int ask(int x,int y){ if(t[x].top==x)return count(t[x].pos,y); int tmp=(t[x].data>y); for(int i=first[x][0];i;i=e[i][0].next) if(e[i][0].x!=t[x].fa) tmp+=ask(e[i][0].x,y); return tmp;}void modify(int x,int y){ int p=t[x].pos,n=b[p].v.size(),i; for(i=0;i<n;i++) if(b[p].v[i]==t[x].data)break; t[x].data=b[p].v[i]=y; for(;i<n-1&&b[p].v[i]>b[p].v[i+1];i++) swap(b[p].v[i],b[p].v[i+1]); for(;i>0&&b[p].v[i]<b[p].v[i-1];i--) swap(b[p].v[i],b[p].v[i-1]);}void insert(int x,int y){ add(x,y,0); if(b[t[x].pos].size>=lim){ newnode(y,y,++num); add(t[x].pos,num,1); }else newnode(y,t[x].top,t[x].pos); int i=b[t[y].pos].v.size()-1; for(;i>0&&b[t[y].pos].v[i]<b[t[y].pos].v[i-1];i--) swap(b[t[y].pos].v[i],b[t[y].pos].v[i-1]);}int main(){ scanf("%d",&n); for(int i=1;i<n;i++){ scanf("%d%d",&x,&y); add(x,y,0); add(y,x,0); } for(int i=1;i<=n;i++) scanf("%d",&t[i].data); lim=(int)sqrt(n)*(log(n)/log(2)); bfs(); for(int i=1;i<=num;i++)sort(b[i].v.begin(),b[i].v.end()); scanf("%d",&m); for(int i=1;i<=m;i++){ scanf("%d%d%d",&op,&x,&y); x^=ans; y^=ans; if(op==0) ans=ask(x,y),printf("%d\n",ans); else if(op==1)modify(x,y); else if(op==2) { t[++n].data=y; insert(x,n); } } return 0;}
0 0
- BZOJ3720 Gty的妹子树
- bzoj3720: Gty的妹子树
- [bzoj3720]Gty的妹子树
- [bzoj3720]Gty的妹子树
- BZOJ3720: Gty的妹子树
- Bzoj3720:Gty的妹子树:树分块
- 【bzoj3720】Gty的妹子树 块状树
- BZOJ3720 Gty的妹子树Solution
- [bzoj3720]Gty的妹子树 解题报告
- [bzoj3720][非树分块算法]Gty的妹子树
- 3720: Gty的妹子树
- 3720: Gty的妹子树 块状树
- BZOJ 3720 gty的妹子树
- BZOJ 3720 Gty的妹子树
- bzoj 3720: Gty的妹子树
- [bzoj3744]Gty的妹子序列
- bzoj3744 Gty的妹子序列
- bzoj3744: Gty的妹子序列
- POJ1006|中国剩余定理
- Codeforces Round #339 (Div. 2)-B. Gena's Code(字符串模拟)
- hdoj2036(矢量求任意多边形的面积)
- LUA解析json小demo
- Sublime Text 2 安装python自动补全插件jedi
- bzoj3720: Gty的妹子树
- ZeroMQ to .Net 发布订阅 dotnet体系
- HDU2955(动态规划背包)
- Jquery Scroll 事件
- boost::bind的使用方法
- django 复合主键(composit primary key)
- MySQL Cluster 优点和缺点
- 头像剪裁
- OpenCV图像处理的一些基础