「LibreOJ β Round #2」计算几何瞎暴力

https://loj.ac/problem/517

题解

首先我们如果没有排序这个骚操作的话,可以直接记一下各个数位的前缀和,然后异或标记给全局打,查询的时候先把区间信息提取出来然后整体异或就好了。

对于排序,我们考虑对所有排好序的节点建\(trie\)树,这样即使有全局异或标记,我们也可以在\(trie\)树上完成前缀信息的查询。

然后就做完了。

代码

#include<bits/stdc++.h>
#define N 200009
#define ls ch[cnt][0]
#define rs ch[cnt][1]
using namespace std;
typedef long long ll;
const int maxn=30;
int a[N],n,q;
int ch[N*maxn][2],ct[N*maxn][maxn],size[N*maxn],sm[N][maxn];
int tot,rot;
int tag,nowtag;
ll ton[32],nw;
inline ll rd(){
    ll x=0;char c=getchar();bool f=0;
    while(!isdigit(c)){if(c=='-')f=1;c=getchar();}
    while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
    return f?-x:x;
}
void ins(int &cnt,int x,int p){
    if(!cnt)cnt=++tot;
    size[cnt]++;
    for(int i=0;i<=29;++i)if((1<<i)&x)ct[cnt][i]++;
    if(p<0)return;
    int o=(x&(1<<p))!=0;
    if(o)ins(rs,x,p-1);
    else ins(ls,x,p-1);
}
inline ll getsum(int now){
    memset(ton,0,sizeof(ton));
    if(now>=nw){
        for(int i=0;i<=29;++i)ton[i]+=sm[now][i];
    }
    else{
        int cnt=rot,siz=now;
        for(int i=29;i>=0;--i){
            int lson=ls,rson=rs;
            if(nowtag&(1<<i))swap(lson,rson);
            if(size[lson]>=siz)cnt=lson;
            else{
                for(int j=0;j<=29;++j)ton[j]+=ct[lson][j];
                siz-=size[lson];
                cnt=rson;
            }
        }
        if(siz){
            for(int i=0;i<=29;++i)ton[i]+=(ct[cnt][i]!=0)*siz;
        }
    }
    ll ans=0;
    for(int i=0;i<=29;++i){
        ll ss;
        if(tag&(1<<i))ss=now-ton[i];else ss=ton[i];
    //  cout<<ss<<" ";
        ans+=ss*(1ll<<i);
    }
    //cout<<"??\n";
    return ans;
}
int main(){
//  freopen("1.txt","r",stdin);
//  freopen("out","w",stdout);
    n=rd();
    nw=1;
    for(int i=1;i<=n;++i){
      a[i]=rd();
      for(int j=0;j<=29;++j)sm[i][j]=sm[i-1][j]+((a[i]&(1<<j))!=0);
    }
    q=rd();
    int opt,x,l,r;
    while(q--){
        opt=rd();
        if(opt==1){
            x=rd();x^=tag;
            ++n;a[n]=x;
            for(int j=0;j<=29;++j)sm[n][j]=sm[n-1][j]+((a[n]&(1<<j))!=0);
        }
        else if(opt==2){
            l=rd();r=rd();
            printf("%lld\n",getsum(r)-getsum(l-1));
        }
        else if(opt==3)tag^=rd();
        else if(opt==4){
            nowtag=tag;
            while(nw<=n)ins(rot,a[nw],29),nw++;
        }
    }
    return 0;
}

原文地址:https://www.cnblogs.com/ZH-comld/p/11093089.html

时间: 2024-10-14 03:30:07

「LibreOJ β Round #2」计算几何瞎暴力的相关文章

LibreOJ #517. 「LibreOJ β Round #2」计算几何瞎暴力

二次联通门 : LibreOJ #517. 「LibreOJ β Round #2」计算几何瞎暴力 /* LibreOJ #517. 「LibreOJ β Round #2」计算几何瞎暴力 叫做计算几何 实则毒瘤数据结构 看到xor后 考虑Trie树 Trie树的每一个节点保存的是以当前子树中每个二进制位的个数 给Trie打一个全局xor标记,如果标记这一位是1,就交换它的两个儿子 另外维护一个前缀和 前缀和存的是没sort过的值的和 Trie维护的是sort之后的值 1操作直接在前缀和后加就好

LibreOJ #514. 「LibreOJ β Round #2」模拟只会猜题意

二次联通门 : LibreOJ #514. 「LibreOJ β Round #2」模拟只会猜题意 /* LibreOJ #514. 「LibreOJ β Round #2」模拟只会猜题意 本想打个暴力找找规律 结果交上去就A了... 读入所有数 处理出前缀和 然后枚举区间长度 处理处1~n的答案 后O(1)查询即可 复杂度O(n^2 + m) */ #include <iostream> #include <cstring> #include <cstdio> voi

LibreOJ #515. 「LibreOJ β Round #2」贪心只能过样例

二次联通门 : LibreOJ #515. 「LibreOJ β Round #2」贪心只能过样例 /* LibreOJ #515. 「LibreOJ β Round #2」贪心只能过样例 很显然 贪心方程哦不 dp方程为 f[i][j]=f[i-1][j-k*k] 但是这样的话复杂度就是O(N ^ 5) 那么就用bitset优化一下 就ok了 */ #include <iostream> #include <cstdio> #include <bitset> void

LibreOJ「LibreOJ β Round #4」 游戏

二次联通门 : LibreOJ「LibreOJ β Round #4」 游戏 /* LibreOJ「LibreOJ β Round #4」 游戏 找找规律就会发现.. 当有X的时候,答案跟X个数的奇偶有关 否则就求一下逆序对就好了.. 由于SB的错误..WA了3发才过 然后就签完到走人了 */ #include <cstdio> #include <iostream> #include <cstring> #include <algorithm> #defi

LibreOJ #525. 「LibreOJ β Round #4」多项式

二次联通门 : LibreOJ #525. 「LibreOJ β Round #4」多项式 官方题解 : /* LibreOJ #525. 「LibreOJ β Round #4」多项式 由于会有多种解 所以只需要找出一组特殊解即可 */ #include <cstdio> #include <iostream> void read (int &now) { register char c = getchar (); for (now = 0; !isdigit (c);

LibreOJ #528. 「LibreOJ β Round #4」求和

二次联通门 : LibreOJ #528. 「LibreOJ β Round #4」求和 /* LibreOJ #528. 「LibreOJ β Round #4」求和 题目要求的是有多少对数满足他们的最大公约数的质因子不超过一个 f (x) 表示有多少对数满足最大公约数中含有x^2这个因子 那么f (x) = N / x ^ 2 * M * (x ^ 2) 答案即为所有数字减去不符合要求的数字个数 但是我们发现,可能某对数字的最大公约数含有多个质数平方因子 那么在处理的时候就会重复筛去 这时我

LibreOJ #526. 「LibreOJ β Round #4」子集

二次联通门 : LibreOJ #526. 「LibreOJ β Round #4」子集 /* LibreOJ #526. 「LibreOJ β Round #4」子集 考虑一下,若两个数奇偶性相同 若同为奇数, 那加1后就是偶数, gcd的乘积就一定不是1 偶数相同 那么我们把原数中的偶数分为一个集合,奇数分为一个集合 把互相之间不符合要求的连边 那么问题就转化为了二分图求最大独立集 */ #include <cstdio> #include <iostream> #includ

loj #535. 「LibreOJ Round #6」花火 树状数组求逆序对+主席树二维数点+整体二分

$ \color{#0066ff}{ 题目描述 }$ 「Hanabi, hanabi--」 一听说祭典上没有烟火,Karen 一脸沮丧. 「有的哦-- 虽然比不上大型烟花就是了.」 还好 Shinobu 早有准备,Alice.Ayaya.Karen.Shinobu.Yoko 五人又能继续愉快地玩耍啦! 「噢--!不是有放上天的烟花嘛!」Karen 兴奋地喊道. 「啊等等--」Yoko 惊呼.Karen 手持点燃引信的烟花,「嗯??」 Yoko 最希望见到的是排列优美的烟火,当然不会放过这个机会-

[LOJ#525]「LibreOJ β Round #4」多项式

试题描述 给定一个正整数 k,你需要寻找一个系数均为 0 到 k?1 之间的非零多项式 f(x),满足对于任意整数 x 均有 f(x) mod k=0.你给出的多项式次数不能超过 60000,且最高次系数必须非 0. 输入 输入一行,包含一个正整数 k. 输出 若无解,则只输出一个整数 ?1.否则首先输出一个整数 n 表示你寻找的多项式的次数,随后 n+1 个整数按照从低位到高位的顺序输出多项式的系数. 在此之后的输出将被忽略. 输入示例 3 输出示例 4 0 1 2 2 1 数据规模及约定 1