<JZOJ5943>树

一开始t了五个点我就一脸懵逼

然后 发现高级操作...

就是那个tor的数组2333

可以让一些不需要改的不再去改啦

位运算果然是神奇的东西XD

魔性哈哈哈

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#define rint register int
#define MOD 998244353
template <class T>inline void read(T &X)
{
    X=0;int W=0;char ch=0;
    while(!isdigit(ch))W|=ch=='-',ch=getchar();
    while(isdigit(ch))X=(X<<3)+(X<<1)+(ch^48),ch=getchar();
    X=W?-X:X;return;
}

int n,Q,k;
long long ans(0),ans2(0),tree[400010],tpow[400010],tor[400010],a[100010];
void build(int l,int r,int pos)
{
    if(l==r)
    {
        tree[pos]=a[l];
        tpow[pos]=(a[l]*a[l])%MOD;
        tor[pos]=a[l];
        return;
    }
    int mid=l+r>>1;
    build(l,mid,pos<<1);
    build(mid+1,r,pos<<1|1);
    
    tree[pos]=tree[pos<<1]+tree[pos<<1|1];
    tpow[pos]=(tpow[pos<<1]+tpow[pos<<1|1])%MOD;
    tor[pos]=(tor[pos<<1]|tor[pos<<1|1]);
}

void query(int l,int r,int L,int R,int pos)
{
    if(L<=l && r<=R)
    {
        ans+=tree[pos];
        ans2=(ans2+tpow[pos])%MOD;
        return;
    }
    int mid=l+r>>1;
    if(L<=mid)query(l,mid,L,R,pos<<1);
    if(R>mid)query(mid+1,r,L,R,pos<<1|1);
}

void change(int l,int r,int L,int R,int pos)
{
    if((tor[pos]&(~k))==0)return;
    if(l==r)
    {
        tree[pos]=tree[pos]&k;
        a[l]=a[l]&k;
        tor[pos]=a[l];
        tpow[pos]=(a[l]*a[l])%MOD;
        return;
    }
    int mid=l+r>>1;
    if(L<=mid)change(l,mid,L,R,pos<<1);
    if(R>mid)change(mid+1,r,L,R,pos<<1|1);
    
    tree[pos]=tree[pos<<1]+tree[pos<<1|1];
    tpow[pos]=(tpow[pos<<1]+tpow[pos<<1|1])%MOD;
    tor[pos]=(tor[pos<<1]|tor[pos<<1|1]);
}

int main()
{
//    freopen("seg.in","r",stdin);
//    freopen("seg.out","w",stdout);
    read(n);
    for(rint i=1;i<=n;++i)read(a[i]);
    build(1,n,1);
    read(Q);
    while(Q--)
    {
        int num,l,r;
        read(num);
        if(num==1)
        {
            read(l),read(r),read(k);
            change(1,n,l,r,1);
        continue;
        }
        else
        {
            read(l),read(r);
            ans=0;ans2=0;
            query(1,n,l,r,1);
            if(num==2)
            {
                printf("%lld\n",ans);
            continue;
            }
            if(num==3)
            {
                ans%=MOD;
                ans=(2*ans2%MOD*(r-l+1)%MOD+2*ans%MOD*ans)%MOD;
                printf("%lld\n",ans);
            continue;
            }
        }
    }
}

 

posted @ 2018-11-01 19:14  Thheoo  阅读(108)  评论(0编辑  收藏  举报