【题意】给定n个节点的树,每个节点有一个数字ai,m次操作:修改一个节点的数字,或询问一条树链的数字集合的mex值。n,m<=5*10^4,0<=ai<=10^9。

【算法】树分块+带修改莫队算法

【题解】和【BZOJ】3052: [wc2013]糖果公园 树分块+待修改莫队算法差不多。

区别在于如何处理树链信息。考虑对值域分块,由于>n的数字没用,所以对[0,n]分块,维护每一块所含数字个数。

这样就可以O(1)单点修改,O(√n)查询。(扫描到第一块所含数字不满的块,再块内扫描到第一个没出现的数字)。

复杂度O(n^(5/3)+n^(3/2))。

#include<cmath>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=;
int belong[maxn],be[maxn],first[maxn],tot,cnt,top,deep[maxn],f[maxn][],B,Q;
int st[maxn],c[maxn],n,m,c0,c1,sz[maxn],num[maxn],mx,pre[maxn],ANS[maxn];
bool vis[maxn];
struct edge{int v,from;}e[maxn*];
struct mo{int x,y,pre;}a[maxn];
struct que{int x,y,t,id;}b[maxn];
bool cmp(que a,que b){return belong[a.x]<belong[b.x]||(belong[a.x]==belong[b.x]&&belong[a.y]<belong[b.y])||
(belong[a.x]==belong[b.x]&&belong[a.y]==belong[b.y]&&a.t<b.t);}
void insert(int u,int v){tot++;e[tot].v=v;e[tot].from=first[u];first[u]=tot;}
void dfs(int x,int fa){
int p=top;
for(int j=;(<<j)<=deep[x];j++)f[x][j]=f[f[x][j-]][j-];
for(int i=first[x];i;i=e[i].from)if(e[i].v!=fa){
deep[e[i].v]=deep[x]+;
f[e[i].v][]=x;
dfs(e[i].v,x);
if(top-p>=B){
cnt++;
while(top>p)belong[st[top--]]=cnt;
}
}
st[++top]=x;//
}
int lca(int x,int y){
if(deep[x]<deep[y])swap(x,y);
int d=deep[x]-deep[y];
for(int j=;(<<j)<=d;j++)if(d&(<<j))x=f[x][j];
if(x==y)return x;
for(int j=;j>=;j--)if((<<j)<=deep[x]&&f[x][j]!=f[y][j])x=f[x][j],y=f[y][j];
return f[x][];
}
void rev(int x){
if(c[x]>n){vis[x]^=;return;}
if(!vis[x])sz[be[c[x]]]+=(++num[c[x]]==);
else sz[be[c[x]]]-=(--num[c[x]]==);
vis[x]^=;
}
void modify(int x,int y){
if(!vis[x])c[x]=y;
else rev(x),c[x]=y,rev(x);
}
void solve(int x,int y){
while(x!=y){
if(deep[x]>deep[y])rev(x),x=f[x][];
else rev(y),y=f[y][];
}
}
int calc(){
int r;
for(r=;r<mx;r++)if(sz[r]<Q)break;
for(int i=r*Q;i<=n;i++)if(num[i]==)return i;
return n;
}
int main(){
scanf("%d%d",&n,&m);
for(int i=;i<=n;i++)scanf("%d",&c[i]),pre[i]=c[i];
for(int i=;i<n;i++){
int u,v;
scanf("%d%d",&u,&v);
insert(u,v);insert(v,u);
}
B=(int)(pow(n,2.0/)*0.5)+;
Q=(int)(sqrt(n))+;
for(int i=;i<=n;i++)be[i]=i/Q;mx=n/Q;
dfs(,);
while(top)belong[st[top--]]=cnt;
for(int i=;i<=m;i++){
int s,u,v;
scanf("%d%d%d",&s,&u,&v);
if(!s)a[++c0]=(mo){u,v,pre[u]},pre[u]=v;
else{
if(belong[u]>belong[v])swap(u,v);
b[++c1]=(que){u,v,c0,c1};
}
}
sort(b+,b+c1+,cmp);
for(int i=;i<=b[].t;i++)modify(a[i].x,a[i].y);
solve(b[].x,b[].y);
int L=lca(b[].x,b[].y);
rev(L);ANS[b[].id]=calc();rev(L);
for(int i=;i<=c1;i++){///
for(int j=b[i-].t+;j<=b[i].t;j++)modify(a[j].x,a[j].y);
for(int j=b[i-].t;j>b[i].t;j--)modify(a[j].x,a[j].pre);
solve(b[i-].x,b[i].x);solve(b[i-].y,b[i].y);
int L=lca(b[i].x,b[i].y);
rev(L);ANS[b[i].id]=calc();rev(L);
}
for(int i=;i<=c1;i++)printf("%d\n",ANS[i]);
return ;
}

记得询问先处理1,然后从2开始枚举。

【BZOJ】4129: Haruna’s Breakfast 树分块+带修改莫队算法的更多相关文章

  1. 【BZOJ】3052: [wc2013]糖果公园 树分块+带修改莫队算法

    [题目]#58. [WC2013]糖果公园 [题意]给定n个点的树,m种糖果,每个点有糖果ci.给定n个数wi和m个数vi,第i颗糖果第j次品尝的价值是v(i)*w(j).q次询问一条链上每个点价值的 ...

  2. 莫队 [洛谷2709] 小B的询问[洛谷1903]【模板】分块/带修改莫队(数颜色)

    莫队--------一个优雅的暴力 莫队是一个可以在O(n√n)内求出绝大部分无修改的离线的区间问题的答案(只要问题满足转移是O(1)的)即你已知区间[l,r]的解,能在O(1)的时间内求出[l-1, ...

  3. AC日记——【模板】分块/带修改莫队(数颜色) 洛谷 P1903

    [模板]分块/带修改莫队(数颜色) 思路: 带修改莫队: (伏地膜xxy): 代码: #include <bits/stdc++.h> using namespace std; #defi ...

  4. 【BZOJ-2453&2120】维护队列&数颜色 分块 + 带修莫队算法

    2453: 维护队列 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 653  Solved: 283[Submit][Status][Discuss] ...

  5. 洛谷 P1903 BZOJ 2120 清橙 A1274【模板】分块/带修改莫队(数颜色)(周奕超)

    试题来源 2011中国国家集训队命题答辩 题目描述 墨墨购买了一套N支彩色画笔(其中有些颜色可能相同),摆成一排,你需要回答墨墨的提问.墨墨会像你发布如下指令: 1. Q L R代表询问你从第L支画笔 ...

  6. P1903 【模板】分块/带修改莫队(数颜色)

    题目描述 墨墨购买了一套N支彩色画笔(其中有些颜色可能相同),摆成一排,你需要回答墨墨的提问.墨墨会像你发布如下指令: 1. Q L R代表询问你从第L支画笔到第R支画笔中共有几种不同颜色的画笔. 2 ...

  7. bzoj 3052: [wc2013]糖果公园【树上带修改莫队】

    参考:http://blog.csdn.net/lych_cys/article/details/50845832 把树变成dfs括号序的形式,注意这个是不包含lca的(除非lca是两点中的一个) 然 ...

  8. 洛谷 P1903 【模板】分块/带修改莫队(数颜色)

    题目描述 墨墨购买了一套N支彩色画笔(其中有些颜色可能相同),摆成一排,你需要回答墨墨的提问.墨墨会像你发布如下指令: 1. Q L R代表询问你从第L支画笔到第R支画笔中共有几种不同颜色的画笔. 2 ...

  9. luogu1903 【模板】分块/带修改莫队(数颜色)

    莫队算法模板 推荐阅读这篇博客 #include <algorithm> #include <iostream> #include <cstdio> #includ ...

随机推荐

  1. lintcode-248-统计比给定整数小的数的个数

    248-统计比给定整数小的数的个数 给定一个整数数组 (下标由 0 到 n-1,其中 n 表示数组的规模,数值范围由 0 到 10000),以及一个 查询列表.对于每一个查询,将会给你一个整数,请你返 ...

  2. Qt多线程-QThread

    版权声明:若无来源注明,Techie亮博客文章均为原创. 转载请以链接形式标明本文标题和地址: 本文标题:Qt多线程-QThread     本文地址:http://techieliang.com/2 ...

  3. 【BioCode】根据seq与位点信息截取窗口

    代码说明 sequence24371.txt 以上为所有氨基酸的编号,序列,与位点标记.根据标记为“1”的位点,截取窗口:如下(实验结果): 图示为一个窗口为12的蛋白质片段 2N+1=25: 实现代 ...

  4. openssl 编程

    背景: 生成私钥.公钥 --> 生成AES-key seed[32], iv[16] --> 公钥加密ASE-key, IV,传给Server --> Server用私钥解密,得到A ...

  5. virtualenv是什么?virtualenv的安装及pycharm的配置和使用

    virtualenv是什么? virtualenv是一个创建隔绝的Python环境的工具.virtualenv创建一个包含所有必要的可执行文件的文件夹,用来使用Python工程所需的包.简单的说就是一 ...

  6. 使用nginx反向代理时,如何正确获取到用户的真实ip

    在记录日志的的时候,获取用户的信息,比如用户的ip,浏览器等等信息是十分重要的. 但是在使用nginx反向代理的时候,可能经过转发无法获取到用户的真实的ip, 在此情况下需要配置nginx,让其在转发 ...

  7. C# WebBrowser控件模拟登录

    一.问题点: 1.模拟登录后,如果带有嵌套的iframe嵌套,不好读取iframe内容,可以直接指定iframe抓取网址 2.C# 清除WebBrowser控件的Session和Cookie 参考文档 ...

  8. ZOJ1827_The Game of 31

    这是一个比较经典的博弈题目,今年网赛好像是南京赛上有一个类似的题目. 这种题目是没有一定公式或者函数的,需要自己dp或者搜索解决. 题意为分别给你4张写有1,2,3,4,5,6的卡片共24张,每次轮流 ...

  9. EL语法 ${person.id} 这里面的id指的是实例对象的成员变量

    EL语法 ${person.id} 这里面的id指的是实例对象的成员变量

  10. iOS 通过网络请求获取图片的下载歌曲

    1.导入代理<NSURLConnectionDataDelegate> @interface ViewController ()<NSURLConnectionDataDelegat ...