4763: 雪辉[点分治+可持久化分块]
4763: 雪辉
Time Limit: 39 Sec Memory Limit: 666 MB
Submit: 85 Solved: 51
[Submit][Status][Discuss]
Description
Input
Output
Sample Input
0 0 1 0 0 2 2 0 0 0
2 3
1 2
4 5
3 4
7 8
6 7
5 6
9 10
8 9
4
1 7
3 3
1 1
9 3
Sample Output
HINT
Source
By nzhtl1477
- 如果是一个序列,每次询问区间的mex怎么做
- 分块,预处理任意两块之间的bitset,然后每个询问只需要加入 个数就可以了,复杂度
- 树上同理
- 在树上选择 个点当作关键点,有一个贪心的方法可以保证任意两个关键点之间的距离是 的
- 按深度从大到小枚举树上的每个点,将点x标记为关键点当且仅当 的子树中有一个点到 的距离大于 且不为关键点
- 或者直接随机 个点当作关键点也可以保证复杂度
- 考虑预处理关键点之间的bitset,发现不能套用序列上的做法,因为dfs涉及到撤销,如果套用序列上的做法就需要使用可持久化bitset,复杂度变为
- 考虑将原树重构为 个点的新树,即只有关键点的新树
- 重构树中两点之间连有边当且仅当这两个关键点在原树中形成的链上没有其他关键点
- 重构树的边权是一个bitset,存有这两个关键点之间的数
- 通过这个新的树,可以在 的时间预处理任意两点之间的bitset
- 每个询问是多个树链的并,那么可以搞出每个树链的bitset之后在把他们或起来
- 树链 的答案即相当于 的答案或 的答案, 为 的lca
- 至于为什么不能直接求 的答案,因为预处理的两个点之间的bitset是相对于重构树的,有可能会加入多余的点
- 与序列上的处理方法相似,每个询问只需要加入 个数即到达一个关键点
- 总复杂度
- 因为stl的bitset没法支持询问mex,所以要手写bitset
#include<cstdio> #include<cstring> #include<algorithm> #include<vector> #define OPT __attribute__((optimize("O2"))) using namespace std; typedef unsigned long long ll; template <typename T> OPT inline void read(T &x){T f=1;char ch=getchar();x=0;while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}x*=f; } const ll inf=~0ULL; const int N=1e5+5,M=480,T=7e5+5; struct edge{int v,next;}e[N<<1];int tot=1,head[N]; struct P{int x,y,d,o;P(){}P(int _x,int _y,int _d,int _o){x=_x;y=_y;d=_d;o=_o;} }; int n,m,type,mx,sum,root; int A,B,last; int a[N],b[N]; int f[N],siz[N],dep[N];bool vis[N]; int cnt,cur[30],pos[T][30]; ll pool[T][16],bit[M]; vector<P>G[N]; OPT inline bool cmp(const P &c,const P &d){//按子树根节点排序return c.x<d.x; } OPT inline void add(int x,int y){e[++tot].v=y;e[tot].next=head[x];head[x]=tot;e[++tot].v=x;e[tot].next=head[y];head[y]=tot; } OPT inline void findroot(int x,int fa){//找重心siz[x]=1;f[x]=0;for(int i=head[x];i;i=e[i].next){if(vis[e[i].v]||e[i].v==fa) continue;findroot(e[i].v,x);siz[x]+=siz[e[i].v];f[x]=max(f[x],siz[e[i].v]);}f[x]=max(f[x],sum-siz[x]);if(f[x]<f[root]) root=x; } //对于每个点 //记录(重心,重心到它第一个点,距离,可持久) OPT inline void getdep(int x,int y,int z){//算深度f[x]=y;dep[x]=z;if(z>mx) mx=z;for(int i=head[x];i;i=e[i].next){if(vis[e[i].v]||e[i].v==y) continue; getdep(e[i].v,x,z+1);} } //30块,每块16个数 OPT inline void dfs1(int x,int y,int z){if(y==root) z=x;//修改第b[x]个位置//把bitset的第b[x]>>4个位置的第b[x]&15或上1ULL<<(a[x]&63)int t=cur[b[x]>>4];cur[b[x]>>4]=++cnt;for(int i=0;i<16;i++) pool[cnt][i]=pool[t][i];pool[cnt][b[x]&15]|=1ULL<<(a[x]&63);for(int i=0;i<30;i++) pos[cnt][i]=cur[i];G[x].push_back(P(root,z,dep[x],cnt));for(int i=head[x];i;i=e[i].next){if(vis[e[i].v]||e[i].v==y) continue; dfs1(e[i].v,x,z);}cur[b[x]>>4]=t;//还原 } OPT inline void dfs2(int x,int y,int z){if(y==root) z=x;G[x].push_back(P(root,z,dep[x],0));for(int i=head[x];i;i=e[i].next){if(vis[e[i].v]||e[i].v==y) continue; dfs2(e[i].v,x,z);} } OPT inline void solve(int x){vis[x]=1;mx=0;getdep(x,0,0);if(mx>M) dfs1(x,0,0);else dfs2(x,0,0);for(int i=head[x];i;i=e[i].next){if(vis[e[i].v]) continue;f[0]=sum=siz[e[i].v];findroot(e[i].v,root=0);solve(root);} } OPT inline void visit(int x){//标记状态,即某颜色是否出现了 x=a[x];bit[x>>6]|=1ULL<<(x&63); } OPT inline void chain(int x,int y,int d,int o){//统计x->y这条链状态 if(d>M){for(int i=0;i<30;i++)for(int j=0,k=pos[o][i];j<16;j++)bit[i<<4|j]|=pool[k][j];return ;}for(;x!=y;x=f[x]){if(dep[x]<dep[y]) swap(x,y);visit(x);}visit(x); } OPT inline void work(int x,int y){//拆成链 if(x==y){visit(x);return ;}vector<P>::iterator i=G[x].begin(),j=G[y].begin();vector<P>::iterator p=G[x].end(),q=G[y].end();while(i!=p&&j!=q){if(i->x<j->x){i++;continue;}if(i->x>j->x){j++;continue;}if(i->y==j->y){i++;j++;continue;}if(i->x!=x) chain(x,i->x,i->d,i->o);if(i->x!=y) chain(y,j->x,j->d,j->o);i++;j++;} } OPT inline int ask(){//直接查询有多少个“1” int res=0;for(int i=0;i<M;i++) res+=__builtin_popcountll(bit[i]);return res; } OPT inline int mex(){//按块枚举 for(int i=0;;i++) if(bit[i]!=inf)for(int j=0;;j++) if(bit[i]>>j&1^1)return (i<<6)|j; } OPT inline void DFS(int x,int y){//点分治之后,还原树 dep[x]=dep[y]+1;f[x]=y;for(int i=head[x];i;i=e[i].next){if(e[i].v==y) continue; DFS(e[i].v,x);} } OPT int main(){read(n);read(m),read(type);for(int i=1;i<=n;i++) read(a[i]),b[i]=a[i]>>6;;//0<=a[i]<=30000for(int i=1,x,y;i<n;i++) read(x),read(y),add(x,y);f[0]=sum=n;findroot(1,root=0);solve(root);for(int i=1;i<=n;i++) sort(G[i].begin(),G[i].end(),cmp);DFS(1,0);for(int k,x,y;m--;memset(bit,0,sizeof bit)){for(read(k);k--;){read(x);read(y);if(type) x^=last,y^=last;work(x,y); }A=ask();B=mex();printf("%d %d\n",A,B);last=A+B;}return 0; }
转载于:https://www.cnblogs.com/shenben/p/6849597.html
4763: 雪辉[点分治+可持久化分块]相关推荐
- [BZOJ 4763]雪辉
[BZOJ 4763] 雪辉 题意 给定一棵 \(n\) 个点的无根树, 点带权. \(q\) 次询问, 每次给定树上的若干路径, 求这些路径上的点共有多少种不同权值以及这些点的权值组成的集合的 \( ...
- bzoj 4763: 雪辉
Description 给一个n个点的树,点有点权,有m次询问,每次询问多条链的并有多少种不同的点权以及它的mex mex就是一个集合中最小的没有出现的非负整数,注意0要算 比如说集合是1,9,2,6 ...
- [BZOJ4763][P3603]雪辉[手写bitset+静态分块]
题意:给一个n个点的树,点有点权,有m次询问,每次询问多条链的并有多少种不同的点权以及它的mex mex就是一个集合中最小的没有出现的非负整数,注意0要算 rand出 \(\sqrt n\)个点,把每 ...
- [bzoj4763]雪辉[bzoj4812][Ynoi2017]由乃打扑克
来自FallDream的博客,未经允许,请勿转载,谢谢. cut掉部分题面. 给一个n个点的树,点有点权,有m次询问,每次询问多条链的并有多少种不同的点权以及它的mex mex就是一个集合中最小的没有 ...
- Bzoj4763 雪辉
Time Limit: 39 Sec Memory Limit: 666 MB Submit: 151 Solved: 80 Description 上次立下的NOIP退役Flag没有成功 这次就 ...
- 「BZOJ4763」雪辉
「BZOJ4763」天野雪辉 题目大意:有一棵 \(n\) 个点的树,树上每一个点有权值 \(a_i \leq 30000\) ,每次询问给出若干路径,求出这些路径的并上面的不同颜色数与 \(mex\ ...
- [洛谷]CON1466 洛谷2017春节联欢赛 Hello Dingyou题解 Bzoj4763雪辉
题目来源:https://www.luogu.org/contest/show?tid=1466 创建时间:2017/3/13 18:33 镇楼图: 猜猜她是谁~ 解题思路: 春节居然也有 ...
- [Codeforces757G]Can Bash Save the Day?——动态点分治(可持久化点分树)
题目链接: Codeforces757G 题目大意:给出一棵n个点的树及一个1~n的排列pi,边有边权,有q次操作: 1 l r x 求 $\sum\limits_{i=l}^{r}dis(p_{i} ...
- 2019.01.13 bzoj4137: [FJOI2015]火星商店问题(线段树分治+可持久化01trie)
传送门 题意:序列上有nnn个商店,有两种事件会发生: sss商店上进购标价为vvv的一个物品 求编号为[l,r][l,r][l,r]之间的位置买ddd天内新进购的所有物品与一个数xxx异或值的最大值 ...
最新文章
- ICRA2021 SLAM方向论文汇总
- 在Python中访问字典中的任意元素
- android udp 收发例子_如何利用光衰减器来测试光纤收发器的灵敏度?
- 淘宝上线了新功能,有点元宇宙的意思了
- java 构建树形结构_Java求助:如何建立一个树形结构
- [转]Zend Framework + Smarty 应用实例
- [渝粤教育] 西南科技大学 旅客运输组织 在线考试复习资料
- 循道丨全球最大资管公司贝莱德的崛起
- Linux 下子线程 exit code 在主线程中的使用
- Android音视频【七】H265硬编解码视频通话
- 第14章-cpp代码重用(其他继承模板)
- linux系统有哪些
- 【2022/1/12】think-swoole使用教程
- 小明身高180cm,小刚身高165cm,计算两人的身高差
- excel插入散点图按时刻设置横坐标刻度值
- IntelliJ IDEA 下载安装(含注册码)
- 多通道声源定位方法之GCC-PHAT:原理及matlab实现
- 云服务器 ipv6,开通IPv6
- java开发工程师的晋升路径_Java开发工程师职业发展及晋升路线图
- 如何提升计算机的网络性能,计算机优化及性能提升一点通
热门文章
- python蚂蚁森林自动偷能量_蚂蚁森林自动偷能量 激活 - 『精品软件区』 - 吾爱破解 - LCG - LSG |安卓破解|病毒分析|www.52pojie.cn...
- Android利用zxing生成二维码,识别二维码,中间填充图片超详细、超简易教程
- 最新哔哩哔哩视频弹幕播放器源码+带后台/亲测无错误
- Friday BI Fly | 2016年12月02日晚8点半微信直播交流 地理大数据如何驱动智慧选址第42场...
- [四连测(三)]圆形谷仓
- 阿里云服务器完全卸载AliYun监控教程
- CH37X 文件管理芯片使用及移植指南
- 测试高考体育成绩的软件,高考体育成绩查询
- centos linux 修改系统默认语言设置,centos怎么更改语言设置为中文
- java 科学计数法位数_科学记数法android java