zoukankan      html  css  js  c++  java
  • 【BZOJ4129】Haruna’s Breakfast(树上莫队)

    【BZOJ4129】Haruna’s Breakfast(树上莫队)

    题面

    BZOJ

    Description

    Haruna每天都会给提督做早餐! 这天她发现早饭的食材被调皮的 Shimakaze放到了一棵
    树上,每个结点都有一样食材,Shimakaze要考验一下她。
    每个食材都有一个美味度,Shimakaze会进行两种操作:
    1、修改某个结点的食材的美味度。
    2、对于某条链,询问这条链的美味度集合中,最小的未出现的自然数是多少。即mex值。
    请你帮帮Haruna吧。

    Input

    第一行包括两个整数n,m,代表树上的结点数(标号为1~n)和操作数。
    第二行包括n个整数a1...an,代表每个结点的食材初始的美味度。
    接下来n-1行,每行包括两个整数u,v,代表树上的一条边。
    接下来m 行,每行包括三个整数
    0 u x 代表将结点u的食材的美味度修改为 x。
    1 u v 代表询问以u,v 为端点的链的mex值。

    Output

    对于每次询问,输出该链的mex值。

    Sample Input

    10 10

    1 0 1 0 2 4 4 0 1 0

    1 2

    2 3

    2 4

    2 5

    1 6

    6 7

    2 8

    3 9

    9 10

    0 7 14

    1 6 6

    0 4 9

    1 2 2

    1 1 8

    1 8 3

    0 10 9

    1 3 5

    0 10 0

    0 7 7

    Sample Output

    0

    1

    2

    2

    3

    HINT

    1<=n<=5*10^4

    1<=m<=5*10^4

    0<=ai<=10^9

    题解

    (mex)
    如果放在序列上做很显然是裸的莫队+对数字分块
    放在树上面就树上莫队啊。。。
    大于(n)的值对答案没有任何影响,直接丢掉就行了

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<set>
    #include<map>
    #include<vector>
    #include<queue>
    using namespace std;
    #define ll long long
    #define RG register
    #define MAX 55555
    inline int read()
    {
        RG int x=0,t=1;RG char ch=getchar();
        while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
        if(ch=='-')t=-1,ch=getchar();
        while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
        return x*t;
    }
    int n,m,blk;
    struct Line{int v,next;}e[MAX<<1];
    int h[MAX],cnt=1;
    inline void Add(int u,int v){e[cnt]=(Line){v,h[u]};h[u]=cnt++;}
    int dfn[MAX],G[MAX],tim,gr,f[16][MAX],S[MAX],top,dep[MAX];
    int dfs(int u,int ff)
    {
    	f[0][u]=ff;dfn[u]=++tim;dep[u]=dep[ff]+1;
    	for(int i=1;i<=15;++i)f[i][u]=f[i-1][f[i-1][u]];
    	int ret=0;
    	for(int i=h[u];i;i=e[i].next)
    	{
    		int v=e[i].v;if(v==ff)continue;
    		ret+=dfs(v,u);
    		if(ret>=blk){++gr;while(ret--)G[S[top--]]=gr;ret=0;}
    	}
    	S[++top]=u;
    	return ret+1;
    }
    struct modify{int x,a,b;}p[MAX];
    struct Query{int id,u,v,lb,rb,lm;}q[MAX];
    bool operator<(Query a,Query b)
    {
    	if(a.lb!=b.lb)return a.lb<b.lb;
    	if(a.rb!=b.rb)return a.rb<b.rb;
    	return a.lm<b.lm;
    }
    int LCA(int u,int v)
    {
    	if(dep[u]<dep[v])swap(u,v);
    	for(int i=15;~i;--i)if(dep[f[i][u]]>=dep[v])u=f[i][u];
    	if(u==v)return u;
    	for(int i=15;~i;--i)if(f[i][u]!=f[i][v])u=f[i][u],v=f[i][v];
    	return f[0][u];
    }
    int cnt1,cnt2,a[MAX],pre[MAX],nblk;
    int sum[MAX],sblk[MAX];
    bool vis[MAX];
    void Change(int x)
    {
    	if(a[x]>n)return;
    	if(vis[x])--sum[a[x]]?x:--sblk[(a[x])/nblk];
    	else sum[a[x]]++?x:++sblk[(a[x])/nblk];
    	vis[x]^=1;
    }
    void ModifyLink(int u,int v)
    {
    	while(u!=v)
    		if(dep[u]<dep[v])Change(v),v=f[0][v];
    		else Change(u),u=f[0][u];		
    }
    int Mex()
    {
    	for(int i=0;;++i)
    		if(sblk[i]!=nblk)
    			for(int j=0;j<nblk;++j)
    				if(!sum[i*nblk+j])return i*nblk+j;
    }
    void ModifyVal(int x,int c)
    {
    	if(!vis[x])a[x]=c;
    	else Change(x),a[x]=c,Change(x);
    }
    int Ans[MAX];
    int main()
    {
    	n=read();m=read();blk=pow(n,0.66);nblk=sqrt(n);
    	for(int i=1;i<=n;++i)a[i]=pre[i]=read();
    	for(int i=1,u,v;i<n;++i)u=read(),v=read(),Add(u,v),Add(v,u);
    	dfs(1,0);
    	for(int i=1;i<=m;++i)
    	{
    		int opt=read(),u=read(),v=read();
    		if(opt==0)p[++cnt2]=(modify){u,pre[u],v},pre[u]=v;
    		else
    		{
    			if(dfn[u]>dfn[v])swap(u,v);
    			++cnt1,q[cnt1]=(Query){cnt1,u,v,G[u],G[v],cnt2};
    		}
    	}
    	sort(&q[1],&q[cnt1+1]);
    	int lca=LCA(q[1].u,q[1].v),pos=0;
    	while(pos<q[1].lm)++pos,ModifyVal(p[pos].x,p[pos].b);
    	ModifyLink(q[1].u,q[1].v);Change(lca);Ans[q[1].id]=Mex();Change(lca);
    	for(int i=2;i<=cnt1;++i)
    	{
    		while(pos<q[i].lm)++pos,ModifyVal(p[pos].x,p[pos].b);
    		while(pos>q[i].lm)ModifyVal(p[pos].x,p[pos].a),pos--;
    		ModifyLink(q[i-1].u,q[i].u);ModifyLink(q[i-1].v,q[i].v);
    		lca=LCA(q[i].u,q[i].v);
    		Change(lca);Ans[q[i].id]=Mex();Change(lca);
    	}
    	for(int i=1;i<=cnt1;++i)printf("%d
    ",Ans[i]);
    	return 0;
    }
    
    
  • 相关阅读:
    前导问题word使用技巧解决Word 生成目录时前导符不一致的问题(即通常所谓的目录中省略号大小不一致)
    安装用户debian7安装oracle11g
    字节文件MP3格式音频文件结构解析
    Linux下硬盘分区的最佳方案
    802.1x客户端软件 2.4版破解支持多网卡
    z9jpz.dll、gq0aku0.exe、cms2cmw.sys病毒
    Ghost批处理文件的基本格式
    利用ASP远程注册DLL的方法
    dllhost.exe系统进程介绍
    Unicode 和多字节字符集 (MBCS)
  • 原文地址:https://www.cnblogs.com/cjyyb/p/8733390.html
Copyright © 2011-2022 走看看