BZOJ 4571 美味

Posted on 2016-06-24 16:52  ziliuziliu  阅读(146)  评论(0编辑  收藏  举报

又一部SCOI血泪史。。。。

唉。

就是在这棵树上一遍又一遍跑嘛。

以后不要直接求答案啊。要最后再异或起来。

要学习简单的代码风格。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define maxn 200500
#define maxm 4005000
#define inf 262143
using namespace std;
int n,m,a[maxn],root[maxn],tot=0,tree[maxm][3],sum[maxm];
int b,x,l,r;
void insert(int last,int &now,int left,int right,int p)
{
    now=++tot;
    tree[now][1]=tree[last][1];tree[now][2]=tree[last][2];
    sum[now]=sum[last]+1;
    if (left==right) return;
    int mid=(left+right)>>1;
    if (p<=mid) insert(tree[last][1],tree[now][1],left,mid,p);
    else insert(tree[last][2],tree[now][2],mid+1,right,p);
}
bool query(int last,int now,int left,int right,int l,int r)
{
    if ((left==l) && (right==r))
        return sum[now]-sum[last]>0;
    int mid=(left+right)>>1;
    if (r<=mid) return query(tree[last][1],tree[now][1],left,mid,l,r);
    else if (l>=mid+1) return query(tree[last][2],tree[now][2],mid+1,right,l,r);
    else return query(tree[last][1],tree[now][1],left,mid,l,mid)||query(tree[last][2],tree[now][2],mid+1,right,mid+1,r);
}
int main()
{
    scanf("%d%d",&n,&m);
    for (int i=1;i<=n;i++)
        scanf("%d",&a[i]);
    for (int i=1;i<=n;i++)
        insert(root[i-1],root[i],0,inf,a[i]);
    for (int i=1;i<=m;i++)
    {
        scanf("%d%d%d%d",&b,&x,&l,&r);
        int ans=0;
        for (int d=17;d>=0;d--)
        {
            int tmp=b&(1<<d);
            if (tmp)
            {
                int ll=max(ans-x,0),rr=min(ans+(1<<d)-1-x,inf);
                if (!query(root[l-1],root[r],0,inf,ll,rr)) ans^=(1<<d);
            }
            else
            {
                ans^=(1<<d);
                int ll=max(ans-x,0),rr=min(ans+(1<<d)-x-1,inf);
                if (!query(root[l-1],root[r],0,inf,ll,rr)) ans^=(1<<d);
            }
        }
        printf("%d\n",b^ans);
    }
    return 0;
}