博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
bzoj 3720: Gty的妹子树
阅读量:5233 次
发布时间:2019-06-14

本文共 2280 字,大约阅读时间需要 7 分钟。

3720: Gty的妹子树

Time Limit: 10 Sec  Memory Limit: 128 MB

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

2
1 2
10 20
1
0 1 5

Sample Output

2
树上分块,块与块之间是树的关系
首先将树以根号n为标准分为根号n块,怎么分呢?
对于每个节点,维护
siz[],以其为根的子树的大小
bl[],它属于哪一块
开始所有的siz[i]=1,bl[i]=i
然后在dfs过程中合并这n块,
当到i的子节点时,若父节点siz[]<根号n时,点i与他的父节点合并为一块
父节点siz[]=根号n,点i另成一块,并与父节点所在块之间连一条边
查询操作:
属于一整块的二分,不属于一块的枚举
什么意思呢?
每一块肯定都有一个根节点,即bl[i]=i的点
所以若bl[x]=x,那就二分x所在块,否则就枚举x的每个儿子
修改操作:
二分找到块内位置,直接修改,然后排序
添加操作:
如果父节点所在块大小<S,加到父节点所在块内
否则,自己另成一块,并与父节点所在块连一条边
小细节:
块与块之间连边的时候,由父节点所在块向子节点所在块连单向边,
这样在查询的时候,查询同一整块保证了从x一直往下查
或者连双向边,对于每个点记录deep[]表示点的深度
查询的时候,若下一个块的根节点的deep<当前块的根节点的deep,就跳过
#include
#include
#include
#include
#define N 30001using namespace std;int n,m,tot,S,last,ans;int front[N*2],nextt[N*4],to[N*4],Fa[N*2];int w[N*2];int siz[N*2],bl[N*2];vector
g[N*2];vector
block[N*2];void add(int u,int v){ to[++tot]=v;nextt[tot]=front[u];front[u]=tot; to[++tot]=u;nextt[tot]=front[v];front[v]=tot;}void dfs(int x){ for(int i=front[x];i;i=nextt[i]) { if(to[i]==Fa[x]) continue; Fa[to[i]]=x; if(siz[x]
y; for(int i=front[x];i;i=nextt[i]) { if(to[i]==Fa[x]) continue; query(to[i],y); } }}void change(int x,int y){ int pos=lower_bound(block[bl[x]].begin(),block[bl[x]].end(),w[x])-block[bl[x]].begin(); block[bl[x]][pos]=y;w[x]=y; sort(block[bl[x]].begin(),block[bl[x]].end());}void insert(int u,int val){ Fa[++n]=u;add(u,n);w[n]=val; if(siz[bl[u]]

 

转载于:https://www.cnblogs.com/TheRoadToTheGold/p/6560137.html

你可能感兴趣的文章
谨慎使用Marker Interface
查看>>
成功安装SQL Server实例后 无法找到SQL Server Configuration Manager工具的解决方案
查看>>
Bootstrap之Bootstrap组件
查看>>
合唱团---2017校招(动态规划)
查看>>
Vue 2.0学习笔记:v-on
查看>>
2019年寒假作业3
查看>>
尊敬的朋友们大家好,最新公告!寒龙联盟上线了。
查看>>
Vue 事件修饰符
查看>>
装饰器来激活生成器
查看>>
jQuery开发入门
查看>>
PowerDesigner设计Name和Comment 替换
查看>>
全栈技术经理——团队管理:每周问问你的团队这这些问题 V1.0
查看>>
两个字段比较是否有重复数据
查看>>
水塘抽样(Reservoir Sampling)问题
查看>>
【linux】su和sudo命令的区别
查看>>
【NOI2015】品酒大会
查看>>
『重构--改善既有代码的设计』读书笔记---Duplicate Observed Data
查看>>
pycharm的list中append的应用
查看>>
python学习笔记01-简单接触
查看>>
关于博客的一点计划
查看>>