zoukankan      html  css  js  c++  java
  • 【 2018 南京网络赛】 H. Set (字典树合并)

    Shinku is very interested in the set. One day, she got nnn sets, and the iii-th number aia_iai is in the iii-th set. But she doesn't think it is interesting enough, so she applies mmm magic to these sets. There are three kinds of magic:

    1 u v1 u v1 u v: If the uuu-th and vvv-th numbers are not in one set, then the Shinku's magic will merge the set containing the uuu-th number and the set containing the vvv-th number.

    2 u2 u2 u: Shinku's magic adds 111 to each number in the set containing the uuu-th number.

    3 u k x3 u k x3 u k x: Shinku can immediately know how many numbers ttt in the set containing the uuu-th number satisfy t≡x(mod 2k)(0≤k≤30,0≤x<2k)tequiv x (mod 2^k)(0 le kle 30,0le x<2^k)tx(mod 2k)(0k30,0x<2k).

    But unfortunately, for some reason the type 333 magic fails. So Shinku wants you to tell her the answer after every type 333 magic.

    Note that there can be multiple numbers with the same value in one set, that is, numbers with the same value will not disappear when merged.

    Input

    The first line contains two integers n,m(1≤n,m≤6×105)n, m(1 le n, m le 6 imes 10^5)n,m(1n,m6×105), the number of initial sets and the number of the magic.

    The second line contains nnn integers. The iii-th number ai(0≤ai≤109)a_i(0 le a_i le 10^9)ai(0ai109) is the number in the iii-th set initially.

    The next mmm lines describe the sequence of magic. The iii-th line describes the iii-th magic. Each magic is a magic as described above.

    Output

    For each type 333 magic, output the answer you are asked to calculate.

    Hint

    After the first operation, the numbers are 2,3,42,3,42,3,4, sets are {2,4}{3}lbrace 2,4 brace lbrace 3 brace{2,4}{3}

    For the second operation, the third number is in {2,4},2≡0(mod21),4≡0(mod21)lbrace 2,4 brace, 2 equiv 0pmod {2^1}, 4 equiv 0pmod {2^1}{2,4},20(mod21),40(mod21), so the answer is 222.

    After the third operation, the numbers are 2,4,42,4,42,4,4, sets are {2,4}{4}lbrace 2,4 brace lbrace 4 brace{2,4}{4}

    After the forth operation, the numbers are 2,4,42,4,42,4,4, sets are {2,4,4}lbrace 2,4,4 brace{2,4,4}

    For the fifth operation, ,the third number is in {2,4,4},2≡0(mod21),4≡0(mod21)lbrace 2,4,4 brace, 2 equiv 0pmod {2^1}, 4 equiv 0pmod {2^1}{2,4,4},20(mod21),40(mod21),
    4≡0(mod21)4 equiv 0pmod {2^1}40(mod21), so the answer is 333.

    样例输入

    3 5
    2 3 4
    1 1 3
    3 3 1 0
    2 2
    1 2 3
    3 3 1 0

    样例输出

    2
    3

    solution:
    网上的题解说这是个套路题目
    mod 2的k次方就是 有多少个数转化为二进制后后k位相同,
    是不是可以联想但前缀,想到前缀应该就能想到字典树了
    。首先发现询问 3 就是相当于求把所有数字倒过来插入一个 trie 以后某个节点上的和。
    把一个 trie 上的数字 +1,相当于交换 0/1 然后在左子树(0) 下递归交换。
    用动态开点优化,防止爆内存,即使这样,也是刚好够内存…………

    并查级加了启发式合并之后之间并没有减少。。。。qaq

    CODE:
      1 #include"bits/stdc++.h"
      2 using namespace std;
      3 typedef long long ll;
      4 const int MAXN=600105;
      5 const int INF=0x3f3f3f3f;
      6 
      7 int ch[MAXN*71][2];
      8 int num[MAXN*71];
      9 int tot=0;
     10 int root[MAXN];
     11 int sze[MAXN];
     12 
     13 int insert(int x){
     14     int nrt=++tot;
     15     num[nrt]=1;//注意k可能为0,所以根节点的值要初始化为1(WA了好久……)
     16     int res=nrt;
     17     bitset<32> s(x);
     18     for(int i=0;i<=31;i++){
     19         ch[nrt][s[i]]=++tot;
     20         num[ch[nrt][s[i]]]++;
     21         nrt=ch[nrt][s[i]];
     22     }
     23     return res;
     24 }
     25 
     26 int merge(int r1,int r2){
     27 
     28     if(r1==0||r2==0)
     29         return r1+r2;
     30     int nrt=++tot;//记得新建节点
     31     num[nrt]=num[r1]+num[r2];//直接合并
     32     ch[nrt][0]=merge(ch[r1][0],ch[r2][0]);
     33     ch[nrt][1]=merge(ch[r1][1],ch[r2][1]);
     34     return nrt;
     35 
     36 }
     37 
     38 void rev(int u){
     39     if(!u)return;
     40     swap(ch[u][0],ch[u][1]);
     41     rev(ch[u][0]);
     42 }
     43 
     44 int query(int x,int k,int rt){
     45     bitset<32> s(x);
     46     int ans=num[rt];//注意k可能为0
     47     int nrt=rt;
     48     for(int i=0;i<k;i++){
     49         ans=num[ch[nrt][s[i]]];
     50         nrt=ch[nrt][s[i]];
     51     }
     52     return ans;
     53 }
     54 
     55 int fa[MAXN];
     56 int find(int x){
     57     return x==fa[x]?x:fa[x]=find(fa[x]);
     58 }
     59 
     60 int a[MAXN];
     61 inline void Mer(int x,int y)
     62 {
     63     if(sze[x]>sze[y])
     64     fa[y]=x,root[x]=merge(root[x],root[y]);
     65     else
     66     {
     67         fa[x]=y;
     68        root[y]=merge(root[x],root[y]);
     69         if(sze[x]==sze[y])sze[y]++;
     70     }
     71 
     72 }
     73 int main(){
     74 
     75     int N,M;
     76     scanf("%d%d",&N,&M);
     77     tot=0;
     78     for(int i=1;i<=N;i++)
     79     {
     80         scanf("%d",&a[i]);
     81         fa[i]=i;
     82         root[i]=insert(a[i]);
     83     }
     84     int op,u,v,k,x;
     85     while(M--){
     86         scanf("%d",&op);
     87         if(op==1){
     88             scanf("%d%d",&u,&v);
     89             int fx=find(u);
     90             int fy=find(v);
     91             if(fx!=fy){
     92                 Mer(fx,fy);
     93             }
     94         }
     95         if(op==2){
     96             scanf("%d",&u);
     97             rev(root[find(u)]);
     98         }
     99         if(op==3){
    100             scanf("%d%d%d",&u,&k,&x);
    101             printf("%d
    ",query(x,k,root[find(u)]));
    102         }
    103     }
    104 
    105     return 0;
    106 }











  • 相关阅读:
    大数据量时(上千万),分页查询该怎么优化
    Nginx常见面试问题
    Tomcat常用的调优手段
    jenkens
    docker环境搭建httprunner接口自动化
    TypeError: string indices must be integers
    接口自动化简单框架
    phpStudy使用手册
    搭建测试环境
    【Linux】测试环境如何搭建?
  • 原文地址:https://www.cnblogs.com/zhangbuang/p/11148134.html
Copyright © 2011-2022 走看看