2018 ICPC Nanjing network game Set (+ trie merge + lazy update)

 

 

 Problem solution: n sets, you want to m operations. There are three kinds of operations. First, merging two sets x and y. Second, the particular set of all numbers up inside. Third, a collection which ask for all the numbers k th power of 2 modulo, the number of digits equal to x.

Idea: We can save a lazy mark for each node, this tag is similar to lazy marker segment tree. Each time the entire collection increases, changing only the lazy marker, and then next time you access this node, when to go to the mark push_down. And this push_down way is as previously said, according to the parity lazy to determine whether the exchange should carry extra and son. For each query, we directly into the trie, the size is determined to a position corresponding to the output node. Note also that the specific operation, make sure that each intervening digital fixed lengths are set to 30, because the number of 0 is required even in a high stored.

 

Reference Code:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int INF=0x3f3f3f3f;
const int maxn=1e6+10;
const int depth=31;

struct Trie{
    #define ls T[x].ch[0]
    #define rs T[x].ch[1]
    int tot;
    struct Node{
        int siz,ch[2],tag;
    } T[maxn<<5];
    void Init(){tot=0;}
    int NewNode(){memset(&T[++tot],0,sizeof(T[0]));return tot;}

    void pushdown(int x)
    {
        int lz=T[x].tag;
        if(lz&1){swap(ls,rs);T[ls].tag++;}
        T[ls].tag+=lz/2; T[rs].tag+=lz/2;
        T[x].tag=0;
    }

    void Insert(int &rt,int x)
    {
        int o=rt?rt:rt=NewNode(),c;
        for(int i=0;i<depth;++i)
        {
            c=x&1; x>>=1; T[o].siz++;
            if(T[o].tag) pushdown(o);
            if(!T[o].ch[c]) T[o].ch[c]=NewNode();
            o=T[o].ch[c];
        }
    }

    int query(int rt,int x,int y)
    {
        int o=rt;
        for(int k=0;k<y;++k)
        {
            if(T[o].tag) pushdown(o);
            o=T[o].ch[x&1];x>>=1;if(!o) break;
        }
        return T[o].siz;
    }

    void Merge(int x,int y)
    {
        T[x].siz+=T[y].siz;
        if(T[x].tag) pushdown(x);
        if(T[y].tag) pushdown(y);
        for(int i=0;i<2;++i)
        {
            if(T[x].ch[i]&&T[y].ch[i]) Merge(T[x].ch[i],T[y].ch[i]);
            if(!T[x].ch[i]&&T[y].ch[i]) T[x].ch[i]=T[y].ch[i];
        }
    }
} trie;

int n,m,rt[maxn],f[maxn];

int find(int x)
{
    return f[x]==x?x:f[x]=find(f[x]);
}

int main()
{
    while(~scanf("%d",&n))
    {
        scanf("%d",&m);
        memset(rt,0,sizeof rt);
        trie.Init();
        for(int i=1;i<=n;i++)
        {
            f[i]=i;
            int x;scanf("%d",&x);
            trie.Insert(rt[i],x);
        }
        while(m--)
        {
            int op,x,y,z;
            scanf("%d",&op);
            if(op==1)
            {
                scanf("%d%d",&x,&y);
                x=find(x); y=find(y);
                if(x!=y) trie.Merge(rt[x],rt[y]),f[y]=x;
            }
            if(op==2)
            {
                scanf("%d",&x);
                trie.T[rt[find(x)]].tag++;
            }
            if(op==3)
            {
                scanf("%d%d%d",&x,&y,&z);
                x=find(x);
                printf("%d\n",trie.query(rt[x],z,y));
            }
        }
    }
    return 0;
}
View Code

 

Guess you like

Origin www.cnblogs.com/songorz/p/11449521.html