BZOJ 4129 树上带修莫队+线段树
思路:
可以先做做BZOJ3585 是序列上的mex
考虑莫队的转移 如果当前数字出现过 线段树上把它置成1
对于询问 二分ans 线段树上查 0到ans的和 是不是ans+1
本题就是把它搞到了序列上 带了个修改…
麻烦一点 本质上是一样的
//By SiriusRen
#include <cmath>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int N=55555;
int n,m,cnt=1,Block,block[N],op,xx,yy,a[N],vis[N],last[N],sum[N],tree[N*8];
int first[N],next[N*2],v[N*2],tot,s[N],top,fa[N][20],cnt1,cnt2,deep[N],Ans[N];
void add(int x,int y){v[tot]=y,next[tot]=first[x],first[x]=tot++;}
void dfs(int x){
for(int i=first[x];~i;i=next[i])
if(v[i]!=fa[x][0])
deep[v[i]]=deep[x]+1,fa[v[i]][0]=x,dfs(v[i]);
s[++top]=x;
if(top==Block){
for(int i=1;i<=top;i++)block[s[i]]=cnt;
cnt++,top=0;
}
}
struct Ask{
int time,id,l,r;Ask(){}
Ask(int T,int I,int L,int R){time=T,id=I,l=L,r=R;}
friend bool operator<(Ask a,Ask b){
if(block[a.l]==block[b.l]){
if(block[a.r]==block[b.r])return a.time<b.time;
return block[a.r]<block[b.r];
}return block[a.l]<block[b.l];
}
}ask[N];
struct Change{
int last,position,num;Change(){}
Change(int L,int P,int nn){last=L,position=P,num=nn;}
}change[N];
void insert(int l,int r,int pos,int num,int f){
if(l==r){tree[pos]=f;return;}
int mid=(l+r)>>1,lson=pos<<1,rson=pos<<1|1;
if(mid<num)insert(mid+1,r,rson,num,f);
else insert(l,mid,lson,num,f);
tree[pos]=tree[lson]+tree[rson];
}
int query(int l,int r,int pos,int L,int R){
if(l>=L&&r<=R)return tree[pos];
int mid=(l+r)>>1,lson=pos<<1,rson=pos<<1|1;
if(mid<L)return query(mid+1,r,rson,L,R);
else if(mid>=R)return query(l,mid,lson,L,R);
else return query(l,mid,lson,L,R)+query(mid+1,r,rson,L,R);
}
void reverse(int x){
vis[x]^=1;
if(a[x]<=n){
if(vis[x]){
sum[a[x]]++;
if(sum[a[x]]==1)insert(0,n,1,a[x],1);
}
else{
sum[a[x]]--;
if(!sum[a[x]])insert(0,n,1,a[x],0);
}
}
}
void change_color(int x,int y){
if(vis[x])reverse(x),a[x]=y,reverse(x);
else a[x]=y;
}
void work(int x,int y){
while(x!=y){
if(deep[x]<deep[y])swap(x,y);
reverse(x),x=fa[x][0];
}
}
int lca(int x,int y){
if(deep[x]<deep[y])swap(x,y);
for(int i=19;i>=0;i--)if(deep[x]-(1<<i)>=deep[y])x=fa[x][i];
if(x==y)return x;
for(int i=19;i>=0;i--)if(fa[x][i]!=fa[y][i])x=fa[x][i],y=fa[y][i];
return fa[x][0];
}
bool check(int x){
return query(0,n,1,0,x)==x+1;
}
int main(){
memset(first,-1,sizeof(first));
scanf("%d%d",&n,&m),Block=sqrt(n);
for(int i=1;i<=n;i++)scanf("%d",&a[i]),last[i]=a[i];
for(int i=1;i<n;i++)scanf("%d%d",&xx,&yy),add(xx,yy),add(yy,xx);
dfs(1);
for(int i=1;i<=top;i++)block[s[i]]=cnt;
for(int j=1;j<=19;j++)
for(int i=1;i<=n;i++)
fa[i][j]=fa[fa[i][j-1]][j-1];
while(m--){
scanf("%d%d%d",&op,&xx,&yy);
if(op==1){
if(block[xx]>block[yy])swap(xx,yy);
ask[++cnt1]=Ask(cnt2,cnt1,xx,yy);
}
else change[++cnt2]=Change(last[xx],xx,yy),last[xx]=yy;
}
sort(ask+1,ask+1+cnt1);
for(int i=1,T=0;i<=cnt1;i++){
for(;T<ask[i].time;T++){
change_color(change[T+1].position,change[T+1].num);
a[change[T+1].position]=change[T+1].num;
}
for(;T>ask[i].time;T--){
change_color(change[T].position,change[T].last);
a[change[T].position]=change[T].last;
}
if(i!=1)work(ask[i-1].l,ask[i].l),work(ask[i-1].r,ask[i].r);
else work(ask[i].l,ask[i].r);
reverse(lca(ask[i].l,ask[i].r));
int l=0,r=n,ans=0;
while(l<=r){
int mid=(l+r)>>1;
if(check(mid))ans=mid+1,l=mid+1;
else r=mid-1;
}
Ans[ask[i].id]=ans;
reverse(lca(ask[i].l,ask[i].r));
}
for(int i=1;i<=cnt1;i++)printf("%d\n",Ans[i]);
}
BZOJ 4129 树上带修莫队+线段树的更多相关文章
- BZOJ 3052 树上带修莫队
思路: 就是把带修莫队移到了树上 块的大小开到(n^2/3)/2 比较好- 这是一个卡OJ好题 //By SiriusRen #include <cmath> #include <c ...
- BZOJ 4129 Haruna’s Breakfast ( 树上带修莫队 )
题面 求树上某路径上最小的没出现过的权值,有单点修改 添加链接描述 分析 树上带修莫队板题,问题是怎么求最小的没出现过的权值. 因为只有nnn个点,所以没出现过的最小值一定在[0,n][0,n][0, ...
- BZOJ 3052/Luogu P4074 [wc2013]糖果公园 (树上带修莫队)
题面 中文题面,难得解释了 BZOJ传送门 Luogu传送门 分析 树上带修莫队板子题... 开始没给分块大小赋初值T了好一会... CODE #include <bits/stdc++.h&g ...
- bzoj4129 Haruna’s Breakfast 树上带修莫队+分块
题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=4129 题解 考虑没有修改的序列上的版本应该怎么做: 弱化的题目应该是这样的: 给定一个序列,每 ...
- 【BZOJ-3052】糖果公园 树上带修莫队算法
3052: [wc2013]糖果公园 Time Limit: 200 Sec Memory Limit: 512 MBSubmit: 883 Solved: 419[Submit][Status] ...
- LUOGU P4074 [WC2013]糖果公园 (树上带修莫队)
传送门 解题思路 树上带修莫队,搞了两天..终于开O2+卡常大法贴边过了...bzoj上跑了183s..其实就是把树上莫队和带修莫队结合到一起,首先求出括号序,就是进一次出一次那种的,然后如果求两个点 ...
- BZOJ3052: [wc2013]糖果公园【树上带修莫队】
Description Input Output Sample Input Sample Input Sample Output 84 131 27 84 HINT 思路 非常模板的树上带修莫队 真的 ...
- luogu4074 [WC2013]糖果公园(树上带修莫队)
link 题目大意:给一个树,树上每个点都有一种颜色,每个颜色都有一个收益 每次修改一个点上的颜色 或询问一条链上所有颜色第i次遇到颜色j可以获得w[i]*v[j]的价值,求链上价值和 题解:树上带修 ...
- 「洛谷1903」「BZOJ2120」「国家集训队」数颜色【带修莫队,树套树】
题目链接 [BZOJ传送门] [洛谷传送门] 题目大意 单点修改,区间查询有多少种数字. 解法1--树套树 可以直接暴力树套树,我比较懒,不想写. 稍微口胡一下,可以直接来一个树状数组套主席树,也就是 ...
随机推荐
- css3 边框、背景、文本效果
浅玩CSS3 边框.背景.文本效果 一.边框 box-shadow box-shadow: h-shadow v-shadow blur spread color inset(ontset); //h ...
- javascript中天气接口案例
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- 揭秘IPHONE X刷脸认证的技术奥秘
苹果最新发布的Iphone X具有一个全新的功能叫做刷脸认证,背后的技术其实是生物密码的更新,通过人脸识别取代了传统的指纹识别,大家肯定对这种新技术非常感兴趣,下面我们通过这篇文章为大家介绍人脸识别的 ...
- hdu4081 Qin Shi Huang's National Road System 次小生成树
先发发牢骚:图论500题上说这题是最小生成树+DFS,网上搜题解也有人这么做.但是其实就是次小生成树.次小生成树完全当模版题.其中有一个小细节没注意,导致我几个小时一直在找错.有了模版要会用模版,然后 ...
- Junit使用第二弹
实例总结 1. 参数化测试 有时一个测试方法,不同的参数值会产生不同的结果,那么我们为了测试全面,会把多个参数值都写出来并一一断言测试,这样有时难免费时费力,这是我们便可以采用参数化测试来解决这个问题 ...
- mvc关于pots请求 哪个函数 出现bug研究
这样能请求home下的updateA函数 这样能请求home下的update函数,不能请求updateA函数
- 图表库 - Highchart / Echart
当前主要使用HighChart和Echart图表库,都基于Jquery,需要先引用Jquery. 实际问题:引入Jquery需在图表库前,否则报错. HighChart官网:https://www.h ...
- ArrayList集合如何存储基本数据类型
ArrayList对象不能存储基本类型,只能存储引用类型的数据.类似 <int> 不能写,但是存储基本数据类型对应的包装类型是可以的. 所以,想要存储基本类型数据, <> 中的 ...
- Git 常用命令速查(转载)
git branch 查看本地所有分支git status 查看当前状态 git commit 提交 git branch -a 查看所有的分支git branch -r 查看远程所有分支git co ...
- BZOJ 1042: [HAOI2008]硬币购物 容斥原理_背包_好题
Description 硬币购物一共有4种硬币.面值分别为c1,c2,c3,c4.某人去商店买东西,去了tot次.每次带di枚ci硬币,买s i的价值的东西.请问每次有多少种付款方法. 题解: 十分喜 ...