[bzoj3720]Gty的妹子树
来源:互联网 发布:锥坡计算软件 编辑:程序博客网 时间:2024/05/01 14:26
3720: Gty的妹子树
Time Limit: 10 Sec Memory Limit: 128 MB
Submit: 963 Solved: 331
[Submit][Status][Discuss]
Description
我曾在弦歌之中听过你,
檀板声碎,半出折子戏。
舞榭歌台被风吹去,
岁月深处尚有余音一缕……
Gty神(xian)犇(chong)从来不缺妹子……
他来到了一棵妹子树下,发现每个妹子有一个美丽度……
由于Gty很哲♂学,他只对美丽度大于某个值的妹子感兴趣。
他想知道某个子树中美丽度大于k的妹子个数。
某个妹子的美丽度可能发生变化……
树上可能会出现一只新的妹子……
维护一棵初始有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。
Input
输入第一行包括一个正整数n(1<=n<=30000),代表树上的初始节点数。
接下来n-1行,每行2个整数u,v,为树上的一条无向边。
任何时刻,树上的任何权值大于等于0,且两两不同。
接下来1行,包括n个整数wi,表示初始时每个节点的权值。
接下来1行,包括1个整数m(1<=m<=30000),表示操作总数。
接下来m行,每行包括三个整数 op,u,v:
op,u,v的含义见题目描述。
保证题目涉及的所有数在int内。
Output
对每个op=0,输出一行,包括一个整数,意义见题目描述。
Sample Input
21 210 2010 1 5
Sample Output
2
我这道题用的是对进栈顺序的
树还有很多分块的方法:
王室联邦那个题就是相当于对出栈顺序的dfs序序列分块的。还可以对子树大小进行限制来分块。...
我是对于
这样每次查询一个子树的时候,从根走完这个块后,看看下一个块的
对于这个题插入节点的问题:每次插入的时候都放到它爸爸后面的第一个,暴力改一下这个块后面的元素在这个块内的顺序。
写完之后
为什么块越大越快呢?
可以这样想一下:每次的查询操作是
这样我们会发现如果块的大小变大的话, 虽然会加大修改的复杂度,但是查询时候的在块中二分的次数会减少很多,所以总体上的复杂度会更优越。
#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#include<cmath>using namespace std;#define inf 0x7fffffffconst int N=60010;struct S{int st,en;}aa[N<<1];struct B{int v,No,num,dep;}block[400][(400+10)<<1];int n,m,tot,point[N],next[N<<1],w[N],o,in[N],min_d[N],to[N],ans,siz[N];inline int IN(){ int x=0;char ch=getchar(); while(ch<'0'||ch>'9') ch=getchar(); while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar(); return x;}inline void add(int x,int y){ next[++tot]=point[x];point[x]=tot; aa[tot].st=x;aa[tot].en=y; next[++tot]=point[y];point[y]=tot; aa[tot].st=y;aa[tot].en=x;}int pos[N],dfsn,deep[N],map[N];inline void dfs(int x,int last){ int i; pos[x]=++dfsn; map[dfsn]=x; for(i=point[x];i;i=next[i]) if(aa[i].en!=last){ deep[aa[i].en]=deep[x]+1; dfs(aa[i].en,x); }}inline bool cmp_v(B x,B y){return x.v>y.v;}inline bool cmp_No(B x,B y){return x.No<y.No;}#define mid (l+r)/2int main(){ int i,j,x,y,t,l,r; n=IN(); int O=(int)(sqrt(n)*0.4); for(i=1;i<n;++i){ x=IN();y=IN(); add(x,y); } for(i=1;i<=n;++i) w[i]=IN(); dfs(1,0); memset(min_d,127,sizeof(min_d)); for(j=o=1,i=1;i<=n;++i){ in[map[i]]=o;++siz[o]; min_d[o]=min(min_d[o],deep[map[i]]); block[o][j].No=j; block[o][j].v=w[map[i]]; block[o][j].num=map[i]; block[o][j].dep=deep[map[i]]; if((++j)>O) j=1,++o; } for(i=1;i<=o;++i) sort(block[i]+1,block[i]+siz[i]+1,cmp_v),to[i]=i+1; to[o]=inf; m=IN(); while(m--){ t=IN();x=IN();y=IN(); x^=ans;y^=ans; int now=in[x]; if(t==0){ bool flag=true; sort(block[now]+1,block[now]+siz[now]+1,cmp_No); for(i=1;i<=siz[now];++i) if(block[now][i].num==x) break; ans=(block[now][i].v>y); int limit=block[now][i].dep; for(i=i+1;i<=siz[now]&&flag;++i) if(block[now][i].dep>limit) ans+=(block[now][i].v>y); else flag=false; sort(block[now]+1,block[now]+siz[now]+1,cmp_v); if(!flag){ printf("%d\n",ans); continue; } for(i=to[now];i&&i!=inf;i=to[i]) if(min_d[i]>limit){ l=1,r=siz[i]; int maxn=0; while(l<=r){ if(block[i][mid].v>y) maxn=max(maxn,mid),l=mid+1; else r=mid-1; } ans+=maxn; } else break; if(i==inf){ printf("%d\n",ans); continue; } sort(block[i]+1,block[i]+siz[i]+1,cmp_No); for(j=1;j<=siz[i]&&block[i][j].dep>limit;++j) ans+=(block[i][j].v>y); sort(block[i]+1,block[i]+siz[i]+1,cmp_v); printf("%d\n",ans); } if(t==1){ for(i=1;i<=siz[now];++i) if(block[now][i].num==x){ block[now][i].v=y; break; } sort(block[now]+1,block[now]+siz[now]+1,cmp_v); } if(t==2){ if(siz[now]+1==O*2){ sort(block[now]+1,block[now]+O*2,cmp_No); ++o;siz[now]=siz[o]=O;++n; to[o]=to[now];to[now]=o; for(i=1;i<O<<1;++i) if(block[now][i].num==x) break; block[now][O<<1].No=block[now][i].No+1; for(i=i+1;i<O<<1;++i) block[now][i].No+=1; block[now][O<<1].v=y; block[now][O<<1].num=n; deep[n]=block[now][O<<1].dep=deep[x]+1; sort(block[now]+1,block[now]+O*2+1,cmp_No); for(i=O+1;i<=O<<1;++i){ block[o][i-O]=block[now][i]; in[block[o][i-O].num]=o; block[o][i-O].No=i-O; } if(!in[n]) in[n]=now; for(min_d[now]=inf,i=1;i<=O;++i) min_d[now]=min(min_d[now],block[now][i].dep); for(min_d[o]=inf,i=1;i<=O;++i) min_d[o]=min(min_d[o],block[o][i].dep); sort(block[now]+1,block[now]+O+1,cmp_v); sort(block[o]+1,block[o]+O+1,cmp_v); } else{ sort(block[now]+1,block[now]+siz[now]+1,cmp_No); in[++n]=now; for(i=1;i<=siz[now];++i) if(block[now][i].num==x) break; block[now][++siz[now]].No=block[now][i].No+1; for(i=i+1;i<siz[now];++i) block[now][i].No+=1; block[now][siz[now]].v=y; block[now][siz[now]].num=n; deep[n]=block[now][siz[now]].dep=deep[x]+1; sort(block[now]+1,block[now]+siz[now]+1,cmp_v); } } }}
- 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的妹子序列
- 由mount引入的相关Linux分析
- HDU 1879 继续畅通工程(Kruskra)
- unity用链表来实现贪吃蛇
- install Chaco——交互式图表
- PDO防sql注入
- [bzoj3720]Gty的妹子树
- 利用mycat实现基于mysql5.5主从复制的读写分离
- 自编码算法与稀疏性
- 并查集(基本代码+poj1182食物链)
- PTA 06-图1 列出连通集
- Linux的XServer
- 动态规划分类
- [Java基础]一个语句交换两个数的值
- Fastboot烧机命令详解