【gdkoi2016】【day1t1】【魔卡少女】【cardcaptor】【线段树】

来源:互联网 发布:网络节点怎么设置 编辑:程序博客网 时间:2024/05/01 06:42

魔卡少女cardcaptor

题意:一段数,支持单点修改,查询一段区间内子区间异或和的和。

具体做法:先做个异或前缀和,[l,r]异或和即sum[i]sum[j](l1<=i,j<=r)(),每个位对答案的贡献为[l1,r]中零的个数乘以一的个数,至于为什么可以自行脑补。对于修改可以把不同的位的[x,n]的零和一的个数调换,对此可以懒标记区间修改,但是一定要记得修改完儿子后,把自己的零和一的个数重新统计一下。为此我调试了半天~~~。可是常数巨大,贴上tle80分的代码。

#include<set>#include<cmath>#include<vector>#include<cstdio>#include<string>#include<cstring>#include<iostream>#include<algorithm>#define ll long long#define fo(i,j,k) for(int i=j;i<=k;i++)#define fd(i,j,k) for(int i=j;i>=k;i--)using namespace std;int const oo=2147483647;int const maxn=100000;int const p=100000007;typedef struct{int x,y;}note;inline int get(){    char ch=getchar();while((ch!='-')&&((ch<'0')||(ch>'9')))ch=getchar();    int u=1,v=0;if(ch=='-')u=-1;else v=ch-'0';ch=getchar();    while((ch>='0')&&(ch<='9'))v=v*10+ch-'0',ch=getchar();    return u*v;}inline char getch(){    char ch=getchar();    while((ch<'A')||(ch>'Z'))ch=getchar();    return ch;}int n,m,a[maxn+10],tr[maxn*6+10][10+1][2],exchange[maxn*6+10][10+1];inline void scan(){    //srand(time(NULL));    //rand()%100;    n=get();    fo(i,1,n)        a[i]=get();}void add(int t,int l,int r,int i,int j,int k){    tr[t][i][j]++;    if(l==r)return;    int m=(l+r)/2;    if(k<=m)add(t*2,l,m,i,j,k);    else add(t*2+1,m+1,r,i,j,k);}void relax(int t,int i){    if(exchange[t][i]){        exchange[t][i]=false;        int tt=tr[t][i][0];        tr[t][i][0]=tr[t][i][1];        tr[t][i][1]=tt;        exchange[t*2][i]=!exchange[t*2][i];        exchange[t*2+1][i]=!exchange[t*2+1][i];    }}void updata(int t,int i){    tr[t][i][0]=tr[t*2][i][0]+tr[t*2+1][i][0];    tr[t][i][1]=tr[t*2][i][1]+tr[t*2+1][i][1];}ll get(int t,int l,int r,int i,int j,int l1,int r1){    relax(t,i);    if((l==l1)&&(r==r1))return tr[t][i][j];    int m=(l+r)/2,ans=0;    if(r1<=m)ans=get(t*2,l,m,i,j,l1,r1);    else if(m<l1)ans=get(t*2+1,m+1,r,i,j,l1,r1);    else ans=get(t*2,l,m,i,j,l1,m)+get(t*2+1,m+1,r,i,j,m+1,r1);    relax(t*2,i);relax(t*2+1,i);    updata(t,i);    return ans;}void change(int t,int l,int r,int i,int l1,int r1){    if((l==l1)&&(r==r1))        exchange[t][i]=!exchange[t][i];    relax(t,i);    if((l==l1)&&(r==r1))return;    int m=(l+r)/2;    if(r1<=m)change(t*2,l,m,i,l1,r1);    else if(m<l1)change(t*2+1,m+1,r,i,l1,r1);    else{        change(t*2,l,m,i,l1,m);        change(t*2+1,m+1,r,i,m+1,r1);    }    relax(t*2,i);relax(t*2+1,i);    updata(t,i);}inline void solve(){    int sum=0;    fo(i,0,n){        int tmp=sum;        fo(j,1,10){            add(1,0,n,j,tmp%2,i);            tmp/=2;        }        sum^=a[i+1];    }    m=get();    fo(i,1,m){        char ch=getch();        int x=get(),y=get();        if(ch=='Q'){            ll ans=0;            fd(j,10,1)                ans=((((1<<(j-1))*get(1,0,n,j,0,x-1,y))%p*get(1,0,n,j,1,x-1,y))%p+ans)%p;            printf("%lld\n",ans);        }        else{            int tmp=y;            fo(j,1,10){                if(a[x]%2!=tmp%2)                    change(1,0,n,j,x,n);                a[x]/=2;                tmp/=2;            }            a[x]=y;        }    }}int main(){    scan();    solve();    return 0;}
1 0