[SCOI2016]bzoj4571 美味 - 贪心 - 线段树

按位贪心即可。


#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#define gc getchar()
#define gv(x,p) (((x)>>p)&1)
#define N 200010
#define M 100010
#define LOG 18
#define debug(x) cerr<<#x<<"="<<x
#define sp <<" "
#define ln <<endl
using namespace std;
inline int inn()
{
    int x,ch;while((ch=gc)<'0'||ch>'9');
    x=ch^'0';while((ch=gc)>='0'&&ch<='9')
        x=(x<<1)+(x<<3)+(ch^'0');return x;
}
struct segment{
    int l,r,mx;segment *ch[2];
}*rt;int a[N];
int build(segment* &rt,int l,int r)
{
    rt=new segment,rt->l=l,rt->r=r,rt->mx=0;
    int mid=(l+r)>>1;if(l==r) return 0;
    return build(rt->ch[0],l,mid),build(rt->ch[1],mid+1,r);
}
inline int push_up(segment* &rt)
{   return rt->mx=max(rt->ch[0]->mx,rt->ch[1]->mx);  }
int update(segment* &rt,int p,int v)
{
    int l=rt->l,r=rt->r,mid=(l+r)>>1;
    if(l==r) return rt->mx=max(rt->mx,v);
    return update(rt->ch[p>mid],p,v),push_up(rt);
}
int query(segment* &rt,int s,int t)
{
    int l=rt->l,r=rt->r,mid=(l+r)>>1;
    if(s<=l&&r<=t) return rt->mx;int ans=0;
    if(s<=mid) ans=max(ans,query(rt->ch[0],s,t));
    if(mid<t) ans=max(ans,query(rt->ch[1],s,t));
    return ans;
}
struct Q{
    int b,x,l,r,id;
    inline bool operator<(const Q &q)const
    {   return r<q.r;    }
}q[M];int ans[M];
int main()
{
    int n=inn(),m=inn();
    for(int i=1;i<=n;i++) a[i]=inn();
    for(int i=1;i<=m;q[i].id=i,i++)
        q[i].b=inn(),q[i].x=inn(),
        q[i].l=inn(),q[i].r=inn();
    sort(q+1,q+m+1),build(rt,1,300010);
    for(int i=1,c=0;i<=m;i++)
    {
        while(c+1<=q[i].r) c++,update(rt,a[c]+1,c);
        for(int j=LOG-1,tmp,b,id,x;j>=0;j--)
        {
            ans[id=q[i].id]|=(1<<j),b=q[i].b,
            x=q[i].x,tmp=((ans[id]^b)>>j)<<j;
            int ql=max(tmp-x,0),qr=tmp+(1<<j)-1-x;
            if(qr<0||query(rt,ql+1,qr+1)<q[i].l) ans[id]^=(1<<j);
        }
    }
    for(int i=1;i<=m;i++) printf("%d\n",ans[i]);return 0;
}

猜你喜欢

转载自blog.csdn.net/Mys_C_K/article/details/81360733