[2018.07.24 T3] 大原题

暂无链接

大原题

【问题描述】

山穷水尽疑无路,柳暗花明又一村。

话不多说——给定一个数列a,你需要支持的操作:区间and,区间or,询问区间最大值。

【输入格式】

一行两个整数n,m,表示数列长度和操作个数。

接下来一行有n个整数,第i个数表示ai。

接下来m行,每一行均为以下三种操作中的一种

1 l r val:ai=ai and val(l≤i≤r)
2 l r val:ai=ai or val(l≤i≤r)
3 l r:max{ai}(l≤i≤r)

【输出格式】

对于每一个3操作,输出一行整数表示对应的答案

【输入样例】

8 6
4 0 5 7 2 9 12 8
2 2 5 15
1 3 5 2
3 5 7
1 5 7 12
2 1 6 4
3 2 6

【输出样例】

12
15

【数据范围】

对于20%的输入数据:n,m ≤ 3000;

另有20%的输入数据:1,2操作中l=r;

另有20%的输入数据:3操作中l=r;

对于100%的输入数据:1 ≤ n,m ≤ 100000 , 0 ≤ ai,val ≤ 10 9

保证所有操作中1 ≤ l ≤ r ≤ n。

数据很有梯度。

题解

真·原题,史上最暖出题人。

&和 | 会把区间内的数逐渐变得一样,如果对于一个区间的数,操作影响的二进制位都是一样的,那么这次操作对所有数的影响都是一样的,原来是最大值的数还是最大值,我们就可以打标记走人了,否则暴力递归下去做修改。

区间内的数二进制位是否一样可以压到一个数里,这个数和位运算的标记可以参考睡觉困难综合征维护。

代码
#include<bits/stdc++.h>
#define ls v<<1
#define rs v<<1|1
using namespace std;
const int M=1e5+5,inf=1073741823;
int que[M],er[M<<2],mx[M<<2],tag0[M<<2],tag1[M<<2],n,m,r;
char c;
int read()
{
    r=0;c=getchar();
    while(!isdigit(c))c=getchar();
    while(isdigit(c))r=(r<<1)+(r<<3)+c-'0',c=getchar();
    return r;
}
void up(int v){mx[v]=max(mx[ls],mx[rs]);er[v]=(er[ls]&er[rs])&(~(mx[ls]^mx[rs]));}
int _new(int x,int t1,int t0){return (~x&t0)|(x&t1);}
void push(int v)
{
    mx[ls]=_new(mx[ls],tag1[v],tag0[v]);mx[rs]=_new(mx[rs],tag1[v],tag0[v]);
    tag0[ls]=_new(tag0[ls],tag1[v],tag0[v]);tag1[ls]=_new(tag1[ls],tag1[v],tag0[v]);
    tag0[rs]=_new(tag0[rs],tag1[v],tag0[v]);tag1[rs]=_new(tag1[rs],tag1[v],tag0[v]);
    tag1[v]=inf;tag0[v]=0;
}
void build(int v,int le,int ri)
{
    tag1[v]=inf;
    if(le==ri){er[v]=inf,mx[v]=que[le];return;}
    int mid=le+ri>>1;build(ls,le,mid);build(rs,mid+1,ri);up(v);
}
bool check(int v,int val,int p){for(int i=1;i<=inf;i<<=1,p<<=1)if((val&i)==p&&!(er[v]&i))return 0;return 1;}
int cha(int v,int val,int p){for(int i=1;i<=inf;i<<=1,p<<=1)if((val&i)==p)er[v]|=i;}
void andd(int v,int le,int ri,int lb,int rb,int val)
{
    if(le==ri){mx[v]&=val;return;}
    if(lb<=le&&ri<=rb&&check(v,val,0)){mx[v]&=val,tag1[v]&=val,tag0[v]&=val,cha(v,val,0);return;}
    int mid=le+ri>>1;push(v);if(lb<=mid)andd(ls,le,mid,lb,rb,val);if(mid<rb)andd(rs,mid+1,ri,lb,rb,val);up(v);
}
void orr(int v,int le,int ri,int lb,int rb,int val)
{
    if(le==ri){mx[v]|=val;return;}
    if(lb<=le&&ri<=rb&&check(v,val,1)){mx[v]|=val,tag1[v]|=val,tag0[v]|=val,cha(v,val,1);return;}
    int mid=le+ri>>1;push(v);if(lb<=mid)orr(ls,le,mid,lb,rb,val);if(mid<rb)orr(rs,mid+1,ri,lb,rb,val);up(v);
}
int ask(int v,int le,int ri,int lb,int rb)
{
    if(lb<=le&&ri<=rb){return mx[v];}
    int mid=le+ri>>1,ans=-1e9;push(v);
    if(lb<=mid)ans=ask(ls,le,mid,lb,rb);if(mid<rb)ans=max(ans,ask(rs,mid+1,ri,lb,rb));up(v);
    return ans;
}
void in(){n=read();m=read();for(int i=1;i<=n;++i)que[i]=read();}
void ac()
{
    int op,le,ri,x;build(1,1,n);
    while(m--)
    {
        op=read(),le=read(),ri=read();
        if(op==1)x=read(),andd(1,1,n,le,ri,x);
        else if(op==2)x=read(),orr(1,1,n,le,ri,x);
        else printf("%d\n",ask(1,1,n,le,ri));
    }
}
int main(){in();ac();}

猜你喜欢

转载自blog.csdn.net/shadypi/article/details/81188228
T3
今日推荐