bzoj4129 Haruna’s Breakfast 莫队
这个思想不难理解了前面几个就能懂
但是代码比较复杂,大概会和之前几次碰到难题的时候一样,一步步思考下去,然后把难点分成好几个板块讲下qwq
首先读入这颗树,预处理下lca,然后就分块,这个时候就会碰到第一个难点了
第一个点是,怎么分块
对不起无法理解无法证明为什么是酱婶的,但是实现并不难qwq
首先明确的是块的大小是n0.45不要问我为什么不会:D
就是如果这个块内的任意俩点距离都小于块的大小,就可以放在一块中
然后这个可以通过dfs+栈实现
代码大概就酱婶的↓
inline void dfs(int x)
{
int gg=cnt;
for(register int i=head[x];i;i=edge[i].next)
{
if(fa[x][]==edge[i].to)continue;
fa[edge[i].to][]=x;deep[edge[i].to]=deep[x]+;
rp(j,,)fa[edge[i].to][j]=fa[fa[edge[i].to][j-]][j-];
dfs(edge[i].to);
if(cnt-gg>=len){++tot;while(cnt!=gg)bl[stck[cnt--]]=tot;}
}
stck[++cnt]=x;
}qwq
分块搞完之后就可以读入修改和询问了,这里就没有太难感觉,用俩结构体就是了
然后排序,就和带修莫队是一样的,不讲
然后就开始解决问题
这个板子题有个很美滋滋的事儿,就是它修改起来特别简单,一路照着链走就是了,然后^修改就是了
但是又会遇到第二个,不算难点,大概是坑点qwq
第二个点是,lca很委屈
显然lca那个点会求两次
所以要另外求一次
那就另外搞个lca的函数求一下就欧克辽嘛
代码也比较简单嘛qwq
inline int lca(int x,int y)
{
if(x==y)return x;if(deep[x]<deep[y])swap(x,y);
my(i,,)if(deep[fa[x][i]]>=deep[y])x=fa[x][i];
my(i,,)if(fa[x][i]!=fa[y][i])x=fa[x][i],y=fa[y][i];
return x==y?x:fa[x][];
}就是个板子嘛QAQ
umm布星我发现我理解还是不够透彻,关于那个直接移动那儿我依然没有理解得十分清楚
所以先咕着了QAQ可能要过一阵子再写QAQ
over
然后原来的代码先放着但是显然是有错误的?先放着趴之后方便改,实在不想全部重码遍了QAQ
#include<bits/stdc++.h>
using namespace std;
#define rp(i,x,y) for(register int i=x;i<=y;++i)
#define my(i,x,y) for(register int i=x;i>=y;--i) const int N=+,sqtN=+;
int now,tot,n,m,c[N],cc[N],len,bl[N],ans[N],cnt;
//umm还是分别写下分工?nm读入不说,c读入和之后莫队修改颜色操作在此处,cc用来搞oldnew的,len是树上块的长度
//bl是树上分块的belong,ans存答案.now是当前时间点,tot开始是树上栈的个数后来是change个数,cnt开始是存边的后来是存栈内元素个数的
int bll[N],cjkcjk,lenlen,num[N],sum[sqtN],sz[sqtN];
//这一行是存查答案那个操作的,bll表示答案的属于,cjkcjk是答案的块个数,lenlen是答案的块的长度,num是每个数个数,sum表示这个块有多少个存在的,sz表示这个块有几个数
int head[N],deep[N],fa[N][],stck[sqtN];
//这一行是专门搞那个边的,比较中规中矩没什么可说的
bool vis[N];
//vis存的是这个点在链上嘛
struct qest{int l,r,id,tim;}q[N];
struct chan{int p,nc,oc;}cg[N];
struct ed{int to,next;}edge[N]; inline int read()
{
char ch=getchar();int x=;bool y=;
while(ch!='-' && (ch<'' || ch>''))ch=getchar();
if(ch=='-')ch=getchar(),y=;
while(ch>='' && ch<='')x=(x<<)+(x<<)+(ch^''),ch=getchar();
return y?x:-x;
}
inline void add(int x,int y){edge[++cnt].to=x;edge[cnt].next=head[y];head[y]=cnt;}
inline bool cmp(qest gold,qest genius){return bl[gold.l]==bl[genius.l]?bl[gold.r]==bl[genius.r]?gold.tim<genius.tim:bl[gold.r]<bl[genius.r]:bl[gold.l]<bl[genius.l];}
inline void ad(int x){sum[bll[x]]+=(++num[x])==;}
inline void dl(int x){sum[bll[x]]-=(--num[x])==;}
inline int as(){rp(i,,cjkcjk)if(sum[i]!=sz[i])rp(j,lenlen*(i-),lenlen*(i-)+sz[i]-)if(!num[j])return j;}
inline void update(int x){if(vis[x])dl(c[x]);else ad(c[x]);vis[x]^=;}
inline void change(int x,int y){if(vis[x])dl(c[x]),ad(y);c[x]=y;}
inline void dfs(int x)
{
int gg=cnt;
for(register int i=head[x];i;i=edge[i].next)
{
if(fa[x][]==edge[i].to)continue;
fa[edge[i].to][]=x;deep[edge[i].to]=deep[x]+;
rp(j,,)fa[edge[i].to][j]=fa[fa[edge[i].to][j-]][j-];
dfs(edge[i].to);
if(cnt-gg>=len){++tot;while(cnt!=gg)bl[stck[cnt--]]=tot;}
}
stck[++cnt]=x;
}
inline int lca(int x,int y)
{
if(x==y)return x;if(deep[x]<deep[y])swap(x,y);
my(i,,)if(deep[fa[x][i]]>=deep[y])x=fa[x][i];
my(i,,)if(fa[x][i]!=fa[y][i])x=fa[x][i],y=fa[y][i];
return x==y?x:fa[x][];
}
inline void move(int x,int y)
{
if(x==y)return;if(deep[x]<deep[y])swap(x,y);
while(deep[x]!=deep[y])update(x),x=fa[x][];
while(x!=y)update(x),update(y),x=fa[x][],y=fa[y][];
}
inline void pre()
{
n=read();m=read();len=pow(n,0.45);
lenlen=sqrt(n);cjkcjk=n/lenlen+;rp(i,,n)bll[i]=(i-)/lenlen+,++sz[(i-)/lenlen+];
rp(i,,n)c[i]=read(),cc[i]=c[i];
rp(i,,n-){int t1=read(),t2=read();add(t1,t2);add(t2,t1);}
cnt=;rp(i,,)fa[][i]=;dfs();++tot;while(cnt)bl[stck[cnt--]]=tot;cnt=;tot=;
rp(i,,m)
{
bool op=read();
if(op)q[i-tot].l=read(),q[i-tot].r=read(),q[i-tot].id=i-tot,q[i-tot].tim=tot;
else cg[++tot].p=read(),cg[tot].nc=read(),cg[tot].oc=cc[cg[tot].p],cc[cg[tot].p]=cg[tot].nc;
}
sort(q+,q++m-tot,cmp);
} int main()
{
pre();
move(q[].l,q[].r);update(lca(q[].l,q[].r));ans[q[].id]=as();
// printf("id=%d l=%d r=%d lca=%d\n",q[1].id,q[1].l,q[1].r,lca(q[1].l,q[1].r));rp(i,1,n)if(vis[i])printf("%d-%d ",i,c[i]);printf("\n\n");
update(lca(q[].l,q[].r));
// printf("\n------------\n");
rp(i,,m-tot)
{
while(now<q[i].tim)change(cg[now+].p,cg[now+].nc),++now;
while(now>q[i].tim)change(cg[now].p,cg[now].oc),--now;
move(q[i].l,q[i-].l);move(q[i].r,q[i-].r);
update(lca(q[i].l,q[i].r));
ans[q[i].id]=as();
// printf("id=%d l=%d r=%d lca=%d ans=%d\n",q[i].id,q[i].l,q[i].r,lca(q[i].l,q[i].r),ans[q[i].id]);
// rp(j,1,n)if(vis[j])printf("%d-%d ",j,c[j]);printf("\n\n");
update(lca(q[i].l,q[i].r));
// printf("\n------------\n");
}
rp(i,,m-tot)printf("%d\n",ans[i]);
return ;
}
太难受了挑了半天然后T了TT
...难受死了不想做这题了,先这样趴至少样例过了?
很烦躁了QAQ
bzoj4129 Haruna’s Breakfast 莫队的更多相关文章
- [BZOJ4129]Haruna’s Breakfast(树上带修改莫队)
BZOJ3585,BZOJ2120,BZOJ3757三合一. 对于树上路径问题,树链剖分难以处理的时候,就用树上带修改莫队. 这里的MEX问题,使用BZOJ3585的分块方法,平衡了时间复杂度. 剩下 ...
- bzoj4129 Haruna’s Breakfast 树上带修莫队+分块
题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=4129 题解 考虑没有修改的序列上的版本应该怎么做: 弱化的题目应该是这样的: 给定一个序列,每 ...
- BZOJ4129: Haruna’s Breakfast
Description Haruna每天都会给提督做早餐! 这天她发现早饭的食材被调皮的 Shimakaze放到了一棵 树上,每个结点都有一样食材,Shimakaze要考验一下她. 每个食材都有一个美 ...
- 【树上莫队】【带修莫队】【权值分块】bzoj4129 Haruna’s Breakfast
#include<cstdio> #include<cstring> #include<algorithm> #include<cmath> using ...
- 【BZOJ4129】Haruna’s Breakfast(树上莫队)
[BZOJ4129]Haruna's Breakfast(树上莫队) 题面 BZOJ Description Haruna每天都会给提督做早餐! 这天她发现早饭的食材被调皮的 Shimakaze放到了 ...
- 【bzoj4129】Haruna’s Breakfast 带修改树上莫队+分块
题目描述 给出一棵树,点有点权.支持两种操作:修改一个点的点权,查询链上mex. 输入 第一行包括两个整数n,m,代表树上的结点数(标号为1~n)和操作数.第二行包括n个整数a1...an,代表每个结 ...
- BZOJ 4129 Haruna’s Breakfast (分块 + 带修莫队)
4129: Haruna’s Breakfast Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 835 Solved: 409[Submit][St ...
- BZOJ 4129: Haruna’s Breakfast [树上莫队 分块]
传送门 题意: 单点修改,求一条链的mex 分块维护权值,$O(1)$修改$O(S)$求mex...... 带修改树上莫队 #include <iostream> #include < ...
- bzoj 4129 Haruna’s Breakfast 树上莫队
按照dfs序分块,莫队乱搞 再套个权值分块 #include<cstdio> #include<iostream> #include<cstring> #inclu ...
随机推荐
- (转)作为一个新人,怎样学习嵌入式Linux?(韦东山)
被问过太多次,特写这篇文章来回答一下. 在学习嵌入式Linux之前,肯定要有C语言基础.汇编基础有没有无所谓(就那么几条汇编指令,用到了一看就会).C语言要学到什么程度呢?越熟当然越好,不熟的话也 ...
- Windows内存放血篇,突破物理内存的CopyOnWrite
本篇以x86(开启PAE) 以及x64 Win7系统 不借助微软API突破内存的写拷贝机制进行讲述 https://bbs.pediy.com/thread-222949.htm 0x01 B ...
- SQL Server 索引结构及其使用(一)[转]
SQL Server 索引结构及其使用(一) 作者:freedk 一.深入浅出理解索引结构 实际上,您可以把索引理解为一种特殊的目录.微软的SQL SERVER提供了两种索引:聚集索引(cluster ...
- aws.s3的 upload 和putObject有什么区别
相同点:上传或新增一个object : <template> <div class="page"> <!-- 参考:https://blog.csdn ...
- Sencha Touch 扩展集合
https://market.sencha.com/extensions http://try.sencha.com/touch/2.1.0/ http://www.mitchellsimoens.c ...
- ubuntu安装vncserver实现图形化访问
请注意: 如果在安装中部分软件无法安装成功,说明软件源中缺包,先尝试使用命令#apt-get update更新软件源后尝试安装.如果还是不行,需要更换软件源.更换步骤: a)输入命令#cp /etc/ ...
- Laravel 5.1 中如何使用模型观察者
有时候我们需要在一个表更改后,触发某个事件,最常见的比如,首页推荐商品 1 更改了,需要清空所有首页商品缓存. 首先我们需要在建立一个观察者类,比如 App\Model\Observers\Proje ...
- stopImmediatePropagation和stopPropagation (事件、防止侦听)
参考: ActionScript 3.0 Step By Step系列(六):学对象事件模型,从点击按扭开始 actionscript宝典 一.事件模型 egret中的事件模型和flash是一样的,但 ...
- centos7搭建ELK开源实时日志分析系统
Elasticsearch 是个开源分布式搜索引擎它的特点有分布式零配置自动发现索引自动分片索引副本机制 restful 风格接口多数据源自动搜索负载等. Logstash 是一个完全开源的工具他可以 ...
- iOS教程:Core Data数据持久性存储基础教程
目录[-] 创建Core Data工程 创建数据模型 测试我们的数据模型 来看看SQL语句的真面目 自动生成的模型文件 创建一个表视图 之后看些什么? 就像我一直说的,Core Data是iOS编程, ...