zoukankan      html  css  js  c++  java
  • 与、或、异或线段树

    题意:

    对区间进行异或  与 或操作   和询问区间和

    对每一位开一棵线段树即可

    #include<cstdio>
    #include<iostream>
    #include<cstring>
    using namespace std;
    #define rep(i,a,b) for(int i=(a);i<=(b);i++)
    #define repp(i,a,b) for(int i=(a);i>=(b);--i)
    #define ll long long
    #define see(x) (cerr<<(#x)<<'='<<(x)<<endl)
    #define inf 0x3f3f3f3f
    #define CLR(A,v)  memset(A,v,sizeof A)
    //////////////////////////////////
    const int N=1e5+100;
    int n,m;
    ll t[25][N<<2],colfan[25][N<<2],col[25][N<<2],a[N];
    void up(int id,int pos)
    {
        t[id][pos]=t[id][pos<<1]+t[id][pos<<1|1];
    }
    void down(int id,int pos,int l,int r)
    {
        int mid=(l+r)>>1;
        if(col[id][pos]!=-1)
        {   
            colfan[id][pos<<1]=colfan[id][pos<<1|1]=0;
            col[id][pos<<1]=col[id][pos<<1|1]=col[id][pos];
            t[id][pos<<1]=1ll*(mid-l+1)*col[id][pos];
            t[id][pos<<1|1]=1ll*(r-mid)*col[id][pos];
            col[id][pos]=-1;
        }
        if(colfan[id][pos]==1)
        {
            colfan[id][pos]=0;
            colfan[id][pos<<1]^=1;
            colfan[id][pos<<1|1]^=1;
            t[id][pos<<1]=1ll*(mid-l+1)-t[id][pos<<1];
            t[id][pos<<1|1]=1ll*(r-mid)-t[id][pos<<1|1];
        }
    }
    void build(int id,int l,int r,int pos)
    {   
        col[id][pos]=-1;colfan[id][pos]=0;
        if(l==r)
        {
            t[id][pos]=( (a[l]>>id)&1 );
            col[id][pos]=0;return ;
        }
        int m=(l+r)>>1;
        build(id,l,m,pos<<1);build(id,m+1,r,pos<<1|1);
        up(id,pos);
    }
    void upfan(int id,int L,int R,int l,int r,int pos)
    {
        if(L<=l&&r<=R)
        {
            t[id][pos]=(r-l+1)-t[id][pos];
            colfan[id][pos]^=1;
            return ;
        }
        int m=(l+r)>>1;down(id,pos,l,r);
        if(L<=m)upfan(id,L,R,l,m,pos<<1);
        if(R>m)upfan(id,L,R,m+1,r,pos<<1|1);
        up(id,pos);
    }
    void upsum(int id,int L,int R,int v,int l,int r,int pos)
    {
        if(L<=l&&r<=R)
        {
            t[id][pos]=(r-l+1)*v;
            col[id][pos]=v;colfan[id][pos]=0;
            return ;
        }
        down(id,pos,l,r);
        int m=(l+r)>>1;
        if(L<=m)upsum(id,L,R,v,l,m,pos<<1);
        if(R>m)upsum(id,L,R,v,m+1,r,pos<<1|1);
        up(id,pos);
    }
    ll qsum(int id,int L,int R,int l,int r,int pos)
    {
        if(L<=l&&r<=R)return t[id][pos];
        int m=(l+r)>>1;ll ans=0;down(id,pos,l,r);
        if(L<=m)ans+=qsum(id,L,R,l,m,pos<<1);
        if(R>m)ans+=qsum(id,L,R,m+1,r,pos<<1|1);
        return ans;
    }
    int main()
    {   
        CLR(col,-1);
        rep(i,1,n)scanf("%lld",&a[i]);
        rep(i,0,22)build(i,1,n,1);
        scanf("%d",&m);
        ll op,l,r,x;
        while(m--)
        {
            scanf("%lld",&op);
            if(op==1)
            {
                scanf("%lld%lld",&l,&r);
                ll ans=0;
                rep(i,0,22)
                ans+=1ll*qsum(i,l,r,1,n,1)*(1ll<<i);
                printf("%lld
    ",ans);
            }
            else if(op==2)
            {
                scanf("%lld%lld%lld",&l,&r,&x);
                rep(i,0,22)
                if( (x>>i)&1 )
                upfan(i,l,r,1,n,1);
            }
            else if(op==3)
            {
                scanf("%lld%lld%lld",&l,&r,&x);
                rep(i,0,22)
                if( (x>>i)&1 )
                upsum(i,l,r,1,1,n,1);
            }
            else if(op==4)
            {
                scanf("%lld%lld%lld",&l,&r,&x);
                rep(i,0,22)
                if( ((x>>i)&1)==0  )
                upsum(i,l,r,0,1,n,1);       
            }
        }
        return 0;
    }
    View Code
  • 相关阅读:
    快排
    装载问题加强版
    從 Internet 安裝 Cygwin
    操作系统:基于页面置换算法的缓存原理详解(上)
    Java设计模式——适配器模式
    Unity 协程使用指南
    2015年总结
    基于正态分布的图片高斯模糊算法
    数据结构:关于AVL树的平衡旋转详解
    算法:关于生成抽样随机数的这些算法
  • 原文地址:https://www.cnblogs.com/bxd123/p/11493515.html
Copyright © 2011-2022 走看看