1. 程式人生 > >【刷題】BZOJ 5312 冒險

【刷題】BZOJ 5312 冒險

cpp int 線段 clu des tput 序列 data out

Description

Kaiser終於成為冒險協會的一員,這次冒險協會派他去冒險,他來到一處古墓,卻被大門上的守護神擋住了去路,守護神給出了一個問題,

只有答對了問題才能進入,守護神給出了一個自然數序列a,每次有一下三種操作。

1,給出l,r,x,將序列l,r之間的所有數都 and x

2,給出l,r,x,將序列l,r之間的所有數都 or x

3,給出l,r,詢問l,r之間的最大值

Input

第一行包含兩個整數 n,m 接下來一行包含 n 個整數, 表示a序列,接下來 m 行, 每行描述了一個操作.

2<=n<=2e5 2<=q<=2e5,0<=ai<=2^20.

Output

對於每個第三類詢問, 輸出一個數字.

Sample Input

3 5
9 19 0
3 2 3
2 3 3 18
1 2 2 10
3 1 2
1 1 3 11

Sample Output

19
9

Solution

線段樹套路題,勢能分析復雜度,如果當前不能同一修改就繼續遞歸
所以這題線段樹每個節點記錄包含區間所有點二進制位相同的有哪些,然後一起修改,如果沒修改完就繼續遞歸

#include<bits/stdc++.h>
#define ui unsigned int
#define ll long long
#define db double
#define ld long double
#define ull unsigned long long
#define REP(a,b,c) for(register int a=(b),a##end=(c);a<=a##end;++a)
#define DEP(a,b,c) for(register int a=(b),a##end=(c);a>=a##end;--a)
const int MAXN=200000+10;
int n,m;
template<typename T> inline void read(T &x)
{
    T data=0,w=1;
    char ch=0;
    while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
    if(ch=='-')w=-1,ch=getchar();
    while(ch>='0'&&ch<='9')data=((T)data<<3)+((T)data<<1)+(ch^'0'),ch=getchar();
    x=data*w;
}
template<typename T> inline void write(T x,char ch='\0')
{
    if(x<0)putchar('-'),x=-x;
    if(x>9)write(x/10);
    putchar(x%10+'0');
    if(ch!='\0')putchar(ch);
}
template<typename T> inline void chkmin(T &x,T y){x=(y<x?y:x);}
template<typename T> inline void chkmax(T &x,T y){x=(y>x?y:x);}
template<typename T> inline T min(T x,T y){return x<y?x:y;}
template<typename T> inline T max(T x,T y){return x>y?x:y;}
#define Mid ((l+r)>>1)
#define ls rt<<1
#define rs rt<<1|1
#define lson ls,l,Mid
#define rson rs,Mid+1,r
struct Segment_Tree{
    int Mx[MAXN<<2],add[MAXN<<2],same[MAXN<<2];
    inline void PushUp(int rt)
    {
        Mx[rt]=max(Mx[ls],Mx[rs]);
        same[rt]=~(Mx[ls]^Mx[rs])&same[ls]&same[rs];
    }
    inline void PushDown(int rt)
    {
        Mx[ls]+=add[rt],add[ls]+=add[rt];
        Mx[rs]+=add[rt],add[rs]+=add[rt];
        add[rt]=0;
    }
    inline void Build(int rt,int l,int r)
    {
        if(l==r)read(Mx[rt]),same[rt]=~0;
        else Build(lson),Build(rson),PushUp(rt);
    }
    inline void Update(int rt,int l,int r,int L,int R,int opt,int k)
    {
        if(L<=l&&r<=R)
        {
            if(opt==1)
            {
                int now=same[rt]&~k;
                add[rt]-=(Mx[rt]&now),Mx[rt]-=(Mx[rt]&now);
                if(!~(k|=now))return ;
            }
            else
            {
                int now=same[rt]&k;
                add[rt]+=(~Mx[rt]&now),Mx[rt]+=(~Mx[rt]&now);
                if(!(k^=now))return ;
            }
        }
        if(add[rt])PushDown(rt);
        if(L<=Mid)Update(lson,L,R,opt,k);
        if(R>Mid)Update(rson,L,R,opt,k);
        PushUp(rt);
    }
    inline int Query(int rt,int l,int r,int L,int R)
    {
        if(L<=l&&r<=R)return Mx[rt];
        else
        {
            if(add[rt])PushDown(rt);
            int tmp=0;
            if(L<=Mid)chkmax(tmp,Query(lson,L,R));
            if(R>Mid)chkmax(tmp,Query(rson,L,R));
            return tmp;
        }
    }
};
Segment_Tree T;
#undef Mid
#undef ls
#undef rs
#undef lson
#undef rson
int main()
{
    read(n);read(m);
    T.Build(1,1,n);
    REP(i,1,m)
    {
        int opt,l,r,x;read(opt);read(l);read(r);
        if(opt==1||opt==2)read(x),T.Update(1,1,n,l,r,opt,x);
        else write(T.Query(1,1,n,l,r),'\n');
    }
    return 0;
}

【刷題】BZOJ 5312 冒險