码迷,mamicode.com
首页 > 其他好文 > 详细

dtoi3701 天照(amaterasu)

时间:2020-02-01 00:44:38      阅读:63      评论:0      收藏:0      [点我收藏+]

标签:else   for   void   can   type   cst   ||   color   之间   

题意:

     给定n个数字a[i],m个询问,每次询问给定l,r,x,求(a[l]+x)xor(a[l+1]+x)xor...xor(a[r]+x)。

题解:

     分开来按位考虑。对于第i位,显然,大于第i位的数值都是没有意义的,可以全部丢掉看做0,无论是a还是x都可以这样处理。

     如果不+x,那么经过处理之后,第i位是1的值只可能在1000...~1111...之间,这是一个连续的区间,那么+x之后依然是一个连续区间(不过有可能会进位,所以要多考虑一种情况,反正都是连续区间),也就是说我们可以很容易得知,第i位是1的数字是在哪一段区间范围内。那么我们只需要求l,r中有多少个数字在这一段区间范围内即可。用可持久化线段树维护就能解决这道题了。

#include<cstdio>
#include<algorithm>
#include<cstdlib>
using namespace std;
int n,m,tp,a[100002],rt[32][100002],cnt,sum[32],ans;
typedef struct{
    int ls,rs;
    bool sum;
}P;
P p[30000002];
void gengxin(int r1,int r2,int begin,int end,int wz){
    if (begin==end)
    {
        p[r2].sum=(p[r1].sum^1);return;
    }
    int mid=begin+(end-begin)/2;
    if (wz<=mid)
    {
        p[r2].ls=++cnt;p[r2].rs=p[r1].rs;
        gengxin(p[r1].ls,p[r2].ls,begin,mid,wz);
    }
    else
    {
        p[r2].rs=++cnt;p[r2].ls=p[r1].ls;
        gengxin(p[r1].rs,p[r2].rs,mid+1,end,wz);
    }
    p[r2].sum=(p[p[r2].ls].sum^p[p[r2].rs].sum);
}
bool chaxun(int r1,int r2,int begin,int end,int begin2,int end2){
    if (begin>end2 || end<begin2)return 0;
    if (begin>=begin2 && end<=end2)return (p[r2].sum^p[r1].sum);
    int mid=begin+(end-begin)/2;
    return (chaxun(p[r1].ls,p[r2].ls,begin,mid,begin2,end2)^chaxun(p[r1].rs,p[r2].rs,mid+1,end,begin2,end2));
}
int main()
{
    sum[0]=1;
    for (int i=1;i<=30;i++)sum[i]=sum[i-1]+(1<<i);
    scanf("%d%d%d",&n,&m,&tp);
    for (int i=1;i<=n;i++)scanf("%d",&a[i]);
    for (int i=1;i<=n;i++)
    {
        for (int j=20;j>=0;j--)
        {
            rt[j][i]=++cnt;
            gengxin(rt[j][i-1],rt[j][i],0,sum[j+1],a[i]);
            if (a[i]&(1<<j))a[i]-=(1<<j);
        }
    }
    for (int i=1;i<=m;i++)
    {
        int l,r,x;
        scanf("%d%d%d",&l,&r,&x);
        l^=(tp*ans);r^=(tp*ans);x^=(tp*ans);
        ans=0;
        for (int j=20;j>=0;j--)
        {
            ans+=(chaxun(rt[j][l-1],rt[j][r],0,sum[j+1],max((1<<j)-x,0),sum[j]-x)^chaxun(rt[j][l-1],rt[j][r],0,sum[j+1],(1<<j+1)+(1<<j)-x,(1<<j+1)+sum[j]-x))*(1<<j);
            if (x&(1<<j))x-=(1<<j);
        }
        printf("%d\n",ans);
    }
    return 0;
}

dtoi3701 天照(amaterasu)

标签:else   for   void   can   type   cst   ||   color   之间   

原文地址:https://www.cnblogs.com/1124828077ccj/p/12247298.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!