2018 ICPC南京网络赛 Set(字典树 + 合并 + lazy更新)

题解:n个集合,你要进行m个操作。总共有3种操作。第一种,合并两个集合x和y。第二张,把特定的集合里面所有的数字加一。第三种,询问在某个集合里面,对于所有数字对2的k次方取模后,有多少个数字等于x。

思路:我们可以对于每一个节点保存一个lazy标记,这个标记类似于线段树中的lazy标记。每次整个集合增加的时候,只改变lazy标记,然后在下一次访问这个节点的时候,再去把这个标记push_down。而这个push_down的方式就是按照之前说的那样,根据lazy的奇偶来判断是否应该交换儿子和额外进位。对于每一个查询操作,我们直接把放到字典树中,确定一个位置,输出对应节点的size即可。具体操作的时候还要注意,一定要把每一个插入的数字固定插入长度设置为30,因为数字的高位即使为0也是需要保存的。

 

参考代码:

#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;
}

原文地址:https://www.cnblogs.com/songorz/p/11449521.html

时间: 2024-08-30 13:48:57

2018 ICPC南京网络赛 Set(字典树 + 合并 + lazy更新)的相关文章

2018 ICPC 徐州网络赛

2018 ICPC 徐州网络赛 A. Hard to prepare 题目描述:\(n\)个数围成一个环,每个数是\(0\)~\(2^k-1\),相邻两个数的同或值不为零,问方案数. solution 将环变成链,设\(f[i][0\)~\(2]\),分别表示与第一个数相同,与第一个数不同,与第一个数相同,与第一个数的反相同.然后\(dp\)即可. 时间复杂度:\(O(n)\) B. BE, GE or NE solution 根据题目描述\(dp\)即可. 时间复杂度:\(O(nm)\) C.

2018 ICPC青岛网络赛 B. Red Black Tree(倍增lca好题)

BaoBao has just found a rooted tree with n vertices and (n-1) weighted edges in his backyard. Among the vertices, of them are red, while the others are black. The root of the tree is vertex 1 and it's a red vertex.Let's define the cost of a red verte

2018 ICPC青岛网络赛 B. Red Black Tree(倍增lca)

BaoBao has just found a rooted tree with n vertices and (n-1) weighted edges in his backyard. Among the vertices, m of them are red, while the others are black. The root of the tree is vertex 1 and it’s a red vertex. Let’s define the cost of a red ve

2019icpc南京网络赛 A 主席树

题意 给一个\(n\times n\)的螺旋矩阵,给出其中的\(m\)个点的值分别为各个点上数字的数位之和,给出\(q\)个询问,每次询问从\((x1,y1)\)到\((x2,y2)\)的子矩阵的和. 分析 用官方题解的方法\(O(1)\)推出点\((x,y)\)上的值,将这\(m\)个点按\(x\)排序后依次按\(y\)建主席树,查询时找到对应的\(x1\)和\(x2\)的历史版本,查询\(y1\)到\(y2\)的权值和就行了,\((query(y1,y2,1,n,rt[l],rt[r]))\

ICPC 2018 徐州赛区网络赛

ACM-ICPC 2018 徐州赛区网络赛 ?去年博客记录过这场比赛经历:该死的水题 ?一年过去了,不被水题卡了,但难题也没多做几道.水平微微有点长进. ? ? D. Easy Math 题意: ? 给定 \(n\), \(m\) ,求 \(\sum _{i=1}^{m} \mu(in)\) .其中 $ 1 \le n \le 1e12$ , $ 1 \le m \le 2e9$ ,\(\mu(n)\) 为莫比乌斯函数. ? 思路: ? 容易知道,\(i\) 与 \(n\) 不互质时, \(\m

2018ICPC南京网络赛

2018ICPC南京网络赛 A. An Olympian Math Problem 题目描述:求\(\sum_{i=1}^{n} i\times i! \%n\) solution \[(n-1) \times (n-1)! \% n= (n-2)!(n^2-2n+1) \%n =(n-2)!\] \[(n-2+1)\times (n-2)! \% n= (n-3)!(n^2-3n+2) \%n =(n-3)! \times 2\] 以此类推,最终只剩下\(n-1\) 时间复杂度:\(O(1)\

2019 ICPC 南昌网络赛

2019 ICPC 南昌网络赛 比赛时间:2019.9.8 比赛链接:The 2019 Asia Nanchang First Round Online Programming Contest 总结 // 史上排名最高一次,开场不到两小时队友各A一题加水题共四题,排名瞬间升至三四十名 // 然后后三小时就自闭了,一题都没有突破...最后排名211 hhhh ? ? B. Fire-Fighting Hero 题意 队友做的,待补. ? AC代码 #include<cstdio> #includ

2019ICPC南京网络赛A题 The beautiful values of the palace(三维偏序)

2019ICPC南京网络赛A题 The beautiful values of the palace https://nanti.jisuanke.com/t/41298 Here is a square matrix of n * nn?n, each lattice has its value (nn must be odd), and the center value is n * nn?n. Its spiral decline along the center of the squar

计蒜客 2018南京网络赛 I Skr ( 回文树 )

题目链接 题意 : 给出一个由数字组成的字符串.然后要你找出其所有本质不同的回文子串.然后将这些回文子串转化为整数后相加.问你最后的结果是多少.答案模 1e9+7 分析 : 应该可以算是回文树挺裸的题目吧 可惜网络赛的时候不会啊.看着马拉车想半天.卒... 对于每一个节点.记录其转化为整数之后的值 然后在回文串插入字符的时候 不断维护这个信息就行了 其实很好理解.看一下代码就懂了 ( 如果你学过回文树的话... ) 就是多加了变量 val .维护语句 #include<bits/stdc++.h