5分。。。。

 

T1 LOJ 计算几何瞎暴力

维护以下操作:

1、序列末尾加一个数

2、序列全体从小到大排序

3、查询区间和

4、序列全体异或一个数k

 

序列全体异或一个数,很明显是trie树

那么序列全体从大到小排序就是把一个个数插入trie树的过程

那么就需要一个数组,存储还没有插入trie树的数

 

全体异或:

这里需要两个标记:

xortag表示当前序列是异或了什么,

trie树里1个tag 表示trie树是在异或了tag之后有序

为什么需要标记?

假设当前是二进制第i位,如果i&标记的第i位为真,那么查询的时候1相当于0,0相当于1

为什么要两个标记?

因为有可能对全体执行异或操作,这样原来有序的trie树直接异或就无序了。

所以tag用来表示trie树在当前tag下是有序的序列

查询子树和时,用xortag

在判断向左还是向右走时,要用trie树里的tag

因为trie树里的顺序不变

 

有了标记,查询区间和时,需要维护的就是二进制的每一位1的出现次数

如果&标记的第i为为真,就用0的个数

否则用1的个数

 

#include<cstdio>
#include<iostream>
using namespace std;
typedef long long LL;
#define N 200001
void read(int &x)
{
    x=0; char c=getchar();
    while(!isdigit(c)) c=getchar();
    while(isdigit(c)) { x=x*10+c-'0'; c=getchar(); }
}
int xortag,bit[31];
struct TRIE
{
    int len,tag,root;
    int ch[N*31][2],sum[N*31][31],siz[N*31];
    TRIE()
    {
        len=0;
        tag=0;
        root=0;
    }
    void insert(int x)
    {
        int rt=root,id;
        for(int i=29;i>=0;--i)
        {
            id=(x&bit[i])>0;
            if(!ch[rt][id]) ch[rt][id]=++len;
            rt=ch[rt][id];
            siz[rt]++;
            for(int j=0;j<30;++j) 
                if(x&bit[j]) sum[rt][j]++;
        }
    }
    LL getsum(int x)
    {
        LL ans=0;
        for(int i=0;i<30;++i)
            if(xortag&bit[i]) ans+=1ll*(siz[x]-sum[x][i])*bit[i];
            else ans+=1ll*sum[x][i]*bit[i];
        return ans;
    }
    LL query(int x)
    {
        if(!x) return 0;
        int rt=root,l,r;
        LL ans=0;
        for(int i=29;i>=0;--i)
        {
            l=0,r=1;
            if(tag&bit[i]) swap(l,r);
            if(x<=siz[ch[rt][l]]) rt=ch[rt][l];
            else
            {
                ans+=getsum(ch[rt][l]);
                x-=siz[ch[rt][l]];
                rt=ch[rt][r];
            }
        }
        ans+=getsum(rt)/siz[rt]*x;
        return ans;
    }
    int getsiz()
    {
        return siz[ch[root][0]]+siz[ch[root][1]];
    }
}Trie;
struct ARRAY
{
    int len;
    ARRAY()
    {
        len=0;
    }
    int sum[N][31],a[N];
    void insert(int x)
    {
        x^=xortag;
        a[++len]=x;
        for(int i=29;i>=0;i--)
            if(x&bit[i]) sum[len][i]=sum[len-1][i]+1;
            else sum[len][i]=sum[len-1][i];
    }
    void transfer()
    {
        Trie.tag=xortag; 
        for(int i=1;i<=len;i++) Trie.insert(a[i]); 
        len=0;
     }
     LL query(int x)
     {
         LL ans=0;
        for(int i=0;i<30;++i)
             if(xortag&bit[i]) ans+=1ll*(x-sum[x][i])*bit[i];
             else ans+=1ll*sum[x][i]*bit[i];
         return ans;
    }
}Array;
LL query(int x)
{
    int siz=Trie.getsiz();
    if(x<=siz) return Trie.query(x);
    else return Trie.query(siz)+Array.query(x-siz);
}
int main()
{
    freopen("seko.in","r",stdin);
    freopen("seko.out","w",stdout);
    bit[0]=1;
    for(int i=1;i<=30;i++) bit[i]=bit[i-1]<<1;
    int n,m,x;
    read(n);
    for(int i=1;i<=n;++i) read(x),Array.insert(x);
    read(m);
    int ty,u,v;
    while(m--)
    {
        read(ty);
        if(ty==1)
        {
            read(v);
            Array.insert(v);
        }
        else if(ty==2) Array.transfer();
        else if(ty==3)
        {
            read(u);read(v);
            printf("%I64d\n",query(v)-query(u-1));
        }
        else 
        {
            read(v);
            xortag^=v;
        }
    }
    return 0;
}
View Code

相关文章:

  • 2021-10-02
  • 2021-11-11
  • 2022-01-10
  • 2021-12-06
  • 2022-02-02
  • 2021-11-27
  • 2021-11-08
  • 2021-10-11
猜你喜欢
  • 2022-01-28
  • 2022-12-23
  • 2022-01-18
  • 2021-10-24
  • 2022-12-23
  • 2021-12-12
  • 2021-10-05
相关资源
相似解决方案