zoukankan      html  css  js  c++  java
  • [9.26模拟赛]T3

    Description

    给定一个有(N)个正整数的初始序列,要求你进行(Q)次操作,每次操作由下列两种内容组成:
    (1) (L) (R):询问(L)(R)的区间和。
    (2) (L) (R) (X):将(L)(R)这个区间里的数都(XOR)(X)

    Input

    第一行两个整数(N)(Q),意义见题目。
    接下来(Q)行,每行第一个数(T1=1) (OR) (T1=2)(T1=1)时,接下来(3)个数(L),(R),(X),否则两个数(L),(R)

    Output

    对于每个操作(2)一行。

    Sample Input

    5 8
    4 10 3 13 7
    1 2 4
    2 1 3 3
    1 2 4
    1 3 3
    2 2 5 5
    1 1 5
    2 1 2 10
    1 2 3

    Sample Output

    26
    22
    0
    34
    11

    Data Constraint

    对于(30)%的数据:(1<=N),(M<=3000)
    对于另外(20)%的数据:数据为纯随机数据。
    对于(100)%的数据:(1<=N<=100000),(1<=M<=50000)(1<=A[i]),(X<=10^6)

    Solution

    我们观察,每个数都小于(10^6),我们把它变成二进制,拆成(20)位,对于每一位都开一个线段树
    比如,第(1)棵线段树的区间([l,r])我们保存从(a[l])(a[r])中的每个数的二进制的第(1)位的(0),(1)的个数
    求和时,当前第(k)位,我们算出当前有a个(1),b个(0),然后把(ans+=a*2^(k-1))
    对于(pushdown),如果修改的数为(x),当前为(k)位,令(h)(x)的第(k)位,则
    如果(h=0),我们不需要修改子树(因为(0)$0=1$,$1$(0=1),相当于没有变过)
    如果(h=1),我们只需要交换当前节点的保存的(0)的个数和(1)的个数,并下传标记(因为(0)$1=1$,$1$(1=0),相当于所有的(0)都变成了(1),所有的(1)都变成了(0)

    Code

    不想写了,CV一下题解代码

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #define ls (t<<1)
    #define rs ((t<<1)+1)
    #define mid ((l+r)>>1)
    using namespace std;
    int i,j,m,n,p,k,l,r,x,kth;
    struct Node{int sum,add;}Tree[32][400001];
    int b[32];
    void down(int Now,int t,int m)
    {  if (!Tree[Now][t].add) return;
       Tree[Now][ls].sum=(m-(m>>1))-Tree[Now][ls].sum;
       Tree[Now][rs].sum=(m>>1)-Tree[Now][rs].sum;
       Tree[Now][ls].add=(Tree[Now][ls].add+1)%2;
       Tree[Now][rs].add=(Tree[Now][rs].add+1)%2;
       Tree[Now][t].add=0;
    }
    void change(int ll,int rr,int l,int r,int t,int Now)
    {  if (ll<=l&&r<=rr) {  Tree[Now][t].sum=(r-l+1)-Tree[Now][t].sum; 
       Tree[Now][t].add=(Tree[Now][t].add+1)%2;  return;}
       down(Now,t,r-l+1);
       if (ll<=mid) change(ll,rr,l,mid,ls,Now);
       if (rr>mid) change(ll,rr,mid+1,r,rs,Now);
       Tree[Now][t].sum=(Tree[Now][ls].sum+Tree[Now][rs].sum);
    }
    void update(int ll,int l,int r,int t,int Now)
    { if (l==r) { Tree[Now][t].sum++; return; }
    if (ll<=mid) update(ll,l,mid,ls,Now);
    else update(ll,mid+1,r,rs,Now);
    Tree[Now][t].sum=(Tree[Now][ls].sum+Tree[Now][rs].sum);
    }
    void Query(int ll,int rr,int l,int r,int t,int Now)
    {  if (ll<=l&&r<=rr) { kth+=Tree[Now][t].sum; return; }
      down(Now,t,r-l+1);
       if (ll<=mid) Query(ll,rr,l,mid,ls,Now);
       if (rr>mid) Query(ll,rr,mid+1,r,rs,Now);
    }
    void ask(int l,int r)
    { int sum=1,i;  long long ans=0;
          for (i=1;i<=30;i++)
         { kth=0; Query(l,r,1,n,1,i); ans=(ans+1ll*kth*sum);
            sum*=2;
         }
        printf("%lld
    ",ans);
    }
    int main()
    { freopen("pc.in","r",stdin);
      freopen("pc.out","w",stdout);
      scanf("%d%d",&n,&m);
      for (i=1;i<=n;i++)
      {  scanf("%d",&p); k=0;
         for (;p;p>>=1)
         {++k;  if (p&1) update(i,1,n,1,k); }
      }
      for (i=1;i<=m;i++) 
      { scanf("%d",&p);
         if (p==1) { scanf("%d%d",&l,&r); ask(l,r); }
         else {  scanf("%d%d%d",&l,&r,&x); k=0; 
           for (;x;x>>=1)
           { ++k; if (x&1) change(l,r,1,n,1,k); }
          }
          }
    }
    
    只要有想见的人,就不是孤身一人了。
  • 相关阅读:
    终于等到你---订餐系统之负载均衡(nginx+memcached+ftp上传图片+iis)
    订餐系统之同步饿了么商家订单
    订餐系统之同步口碑外卖商家菜单与点点送订单
    基于SuperSocket的IIS主动推送消息给android客户端
    基于mina框架的GPS设备与服务器之间的交互
    订餐系统之微信支付,踩了官方demo的坑
    订餐系统之自动确认淘点点订单
    订餐系统之Excel批量导入
    移除首页->重回首页
    订餐系统之获取淘宝外卖订单
  • 原文地址:https://www.cnblogs.com/Agakiss/p/11607437.html
Copyright © 2011-2022 走看看