zoukankan      html  css  js  c++  java
  • 【GDKOI2016】 魔卡少女 线段树

    题目大意:给你一个长度为n的序列${a_1....a_n}$,有$m$次操作

    每次操作有两种情况:修改$a_i$的值,询问$[l,r]$中所有子区间的异或和。

    数据范围:$n,m≤10^5$,$a_i≤1000$。

     

    对于序列$a$,我们对每一个二进制位开一个线段树,对于每个节点,我们存储六个值:

    $sum$:该区间内所有位的异或和。

    $ans$:该区间内所有子区间异或和为1的数量。

    $l_0$:该区间内以区间左端点为起点的所有区间中,异或和为0的区间数量。

    $l_1$:该区间内以区间左端点为起点的所有区间中,异或和为1的区间数量。

    $r_0$:该区间内以区间右端点为起点的所有区间中,异或和为0的区间数量。

    $r_1$:该区间内以区间右端点为起点的所有区间中,异或和为1的区间数量。

    关于pushup的过程,可以参考代码。

    然后随便搞一搞就没了。

     1 #include<bits/stdc++.h>
     2 #define M 400005
     3 #define L long long
     4 #define MOD 100000007
     5 using namespace std;
     6  
     7 struct node{
     8     int l[2],r[2];L sum,ans;
     9     node(){l[0]=l[1]=r[0]=r[1]=sum=ans=0;}
    10     node(int x){
    11         l[1]=r[1]=sum=ans=x;
    12         l[0]=r[0]=x^1;
    13     }
    14     friend node operator +(node a,node b){
    15         node c;
    16         c.sum=a.sum^b.sum;
    17         c.l[0]=a.l[0]+b.l[a.sum];
    18         c.l[1]=a.l[1]+b.l[a.sum^1];
    19         c.r[0]=a.r[b.sum]+b.r[0];
    20         c.r[1]=a.r[b.sum^1]+b.r[1];
    21         c.ans=a.ans+b.ans+1LL*a.r[0]*b.l[1]+1LL*a.r[1]*b.l[0];
    22         return c;
    23     }
    24 };
    25 struct seg{
    26     node a[M];
    27     void updata(int x,int lc,int rc,int k,int op){
    28         if(lc==rc) return void(a[x]=node(op));
    29         int mid=(lc+rc)>>1;
    30         if(k<=mid) updata(x<<1,lc,mid,k,op);
    31         else updata(x<<1|1,mid+1,rc,k,op);
    32         a[x]=a[x<<1]+a[x<<1|1];
    33     }
    34     node query(int x,int lc,int rc,int ll,int rr){
    35         if(ll<=lc&&rc<=rr) return a[x];
    36         int mid=(lc+rc)>>1;
    37         node res;
    38         if(ll<=mid) res=res+query(x<<1,lc,mid,ll,rr);
    39         if(mid<rr) res=res+query(x<<1|1,mid+1,rc,ll,rr);
    40         return res;
    41     }
    42 }p[10];
    43 int n,m; 
    44 int main(){
    45     scanf("%d",&n);
    46     for(int i=1;i<=n;i++){
    47         int x; scanf("%d",&x);
    48         for(int j=0;j<10;j++)
    49         p[j].updata(1,1,n,i,(x>>j)&1);
    50     }
    51     scanf("%d",&m);
    52     while(m--){
    53         char op[10]; int x,y; 
    54         scanf("%s%d%d",op,&x,&y);
    55         if(op[0]=='Q'){
    56             L ans=0;
    57             for(int j=0;j<10;j++){
    58                 node res=p[j].query(1,1,n,x,y);
    59                 ans+=res.ans<<j;
    60             }
    61             printf("%lld
    ",ans%MOD);
    62         }else{
    63             for(int j=0;j<10;j++)
    64             p[j].updata(1,1,n,x,(y>>j)&1);
    65         }
    66     }
    67 }
  • 相关阅读:
    4-vim-工作模式-01-职责以及切换模式
    3-vim-打开和新建文件-02-删除交换文件
    poj1011Stick(dfs+剪枝)
    POJ 1251 Jungle Roads (prim)
    poj 2502 Subway
    poj 3624 Charm Bracelet (01背包)
    拦截导弹问题(动态规划)
    Policy Gradient
    深入了解马尔科夫决策过程(Markov Decision Process)
    深度学习中调参对模型容量的影响
  • 原文地址:https://www.cnblogs.com/xiefengze1/p/9681682.html
Copyright © 2011-2022 走看看