• [BZOJ 4129]Haruna’s Breakfast(树上带修改莫队)


    Description

    Haruna每天都会给提督做早餐! 这天她发现早饭的食材被调皮的 Shimakaze放到了一棵

    树上,每个结点都有一样食材,Shimakaze要考验一下她。
    每个食材都有一个美味度,Shimakaze会进行两种操作:
    1、修改某个结点的食材的美味度。
    2、对于某条链,询问这条链的美味度集合中,最小的未出现的自然数是多少。即mex值。
    请你帮帮Haruna吧。

    Solution

    树上带修改莫队

    统计答案的时候也分块查询,找到第一个没满的块开始一个一个找

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<algorithm>
    #include<cmath>
    #define MAXN 50005
    using namespace std;
    int n,m,a[MAXN],head[MAXN],cnt=0,tot1=0,tot2=0,stack[MAXN],top=0;
    int block,block2,tot3=0,belong[MAXN],last[MAXN],deep[MAXN],p[MAXN][22];
    int ans=0,res[MAXN],num[MAXN],vis[MAXN],sg[MAXN];
    int read()
    {
        int x=0,f=1;char c=getchar();
        while(c<'0'||c>'9'){
            if(c=='-')f=-1;c=getchar();
        }
        while(c>='0'&&c<='9'){
            x=(x<<1)+(x<<3)+c-'0';c=getchar();
        }
        return x*f;
    }
    struct Node1
    {
        int next,to;
    }Edges[MAXN*2];
    void addedge(int u,int v)
    {
        Edges[cnt].next=head[u];
        head[u]=cnt;
        Edges[cnt++].to=v;
    }
    struct Node2
    {
        int u,v,tim,id;
        Node2(int u=0,int v=0,int tim=0,int id=0):u(u),v(v),tim(tim),id(id){}
        bool operator < (const Node2& x) const
        {
            if(belong[u]==belong[x.u])
            {
                if(belong[v]==belong[x.v])
                return tim<x.tim;
                else return belong[v]<belong[x.v]; 
            }
            else return belong[u]<belong[x.u];
        }
    }query[MAXN];
    struct Node3
    {
        int pos,x,pre;
        Node3(int pos=0,int x=0,int pre=0):pos(pos),x(x),pre(pre){}
    }modify[MAXN];
    void dfs(int u)
    {
        int now=top;
        for(int i=head[u];~i;i=Edges[i].next)
        {
            int v=Edges[i].to;
            if(v==p[u][0])continue;
            p[v][0]=u,deep[v]=deep[u]+1;
            dfs(v);
            if(top-now>=block)
            {
                ++tot3;
                while(top!=now)belong[stack[top--]]=tot3;
            }
        }
        stack[++top]=u;
    }
    void init()
    {
        for(int i=1;(1<<i)<=n;i++)
        {
            for(int j=1;j<=n;j++)
            p[j][i]=p[p[j][i-1]][i-1];
        }
    }
    int lca(int a,int b)
    {
        if(deep[a]>deep[b])swap(a,b);
        int f=deep[b]-deep[a];
        for(int i=0;(1<<i)<=f;i++)
        if(f&(1<<i))b=p[b][i];
        if(a!=b)
        {
            for(int i=(int)log2(n);i>=0;i--)
            if(p[a][i]!=p[b][i])a=p[a][i],b=p[b][i];
            a=p[a][0];
        }
        return a;
    }
    void Xor(int pos)
    {
        if(a[pos]>n)return;
        int b=a[pos]/block2+1;
        if(vis[pos])
        {
            num[a[pos]]--;
            if(!num[a[pos]])sg[b]--;
        }
        else
        {
            if(!num[a[pos]])sg[b]++;
            num[a[pos]]++;
        }
        vis[pos]^=1;
    }
    void change(int pos,int c)
    {
        if(vis[pos])
        Xor(pos),a[pos]=c,Xor(pos);
        else a[pos]=c;
    }
    void move(int a,int b)
    {
        if(deep[a]>deep[b])swap(a,b);
        while(deep[a]!=deep[b])Xor(b),b=p[b][0];
        while(a!=b){Xor(a),Xor(b);a=p[a][0],b=p[b][0];}
    }
    void work()
    {
        int u=1,v=1;
        for(int i=1;i<=tot1;i++)
        {
            for(int j=query[i-1].tim+1;j<=query[i].tim;j++)
            change(modify[j].pos,modify[j].x);
            for(int j=query[i-1].tim;j>query[i].tim;j--)
            change(modify[j].pos,modify[j].pre);
            if(u!=query[i].u)move(u,query[i].u),u=query[i].u;
            if(v!=query[i].v)move(v,query[i].v),v=query[i].v;
            int t=lca(u,v);
            Xor(t);
            int k=1;
            while(sg[k]==block2)k++;
            k=(k-1)*block2;
            while(num[k])k++;
            res[query[i].id]=k;
            Xor(t);
        }
    }
    int main()
    {
        memset(head,-1,sizeof(head));
        n=read(),m=read();
        block=pow(n,2.0/3),block2=sqrt(n);
        for(int i=1;i<=n;i++)last[i]=a[i]=read();
        for(int i=1;i<n;i++)
        {
            int u=read(),v=read();
            addedge(u,v);addedge(v,u);
        }
        dfs(1),init();
        for(int i=1;i<=m;i++)
        {
            int opt=read(),x=read(),y=read();
            if(opt)++tot1,query[tot1]=Node2(x,y,tot2,tot1);
            else modify[++tot2]=Node3(x,y,last[x]),last[x]=y;
        }
        sort(query+1,query+1+tot1);
        work();
        for(int i=1;i<=tot1;i++)printf("%d
    ",res[i]);
        return 0;
    }
  • 相关阅读:
    【BZOJ3998】弦论(后缀自动机)
    【BZOJ4566】找相同字符(后缀自动机)
    AtomicInteger在实际项目中的应用
    ElasticSearchserver操作命令
    照猫画虎学gnuplot之折线图
    HDU 5667 :Sequence
    mycat 连续分片 -&gt; 按日期(天)分片
    DM8168 unrecoverable error: OMX_ErrorBadParameter (0x80001005) [resolved]
    多线程(一):初识多线程
    Vb.net/VB 声明API函数实现父窗口功能
  • 原文地址:https://www.cnblogs.com/Zars19/p/6889131.html
Copyright © 2020-2023  润新知