Queries Gym - 100739A

Queries

  Gym - 100739A 
 

XORin discovers an interesting function called Elf. XORina has given XORin an array A of N integers and Q queries. The queries are of 2 types:

1 p x - the element on the position p changes his value to x (Ap=x)

2 a b - find the sum of Elf(i,j) for each a ≤ i ≤ j ≤ b, where Elf(i,j)=Ai xor Ai + 1 xor ... xor Aj.

Your task is to print the responses to the 2nd type of queries.

Input

The first line of the input contains n, the size of the array. The second line of the input contains m, the number of queries (1 ≤ n, m ≤ 100000). The third line of the input contains n numbers, the initial elements of the array (each of them is between 1 and 1000). On the next m lines each line contains a query. The first type of query is 1 p x (1 ≤ p ≤ n and 0 ≤ x ≤ 1000). The second type of query is 2 a b (1 ≤ a ≤ b ≤ n).

Output

The output contains the answer to the second type of queries, each answer on a line. Print the answer modulo 4001.

Examples
Input
4
8
1 2 3 4
2 1 2
1 1 2
2 1 3
2 1 4
1 3 7
2 1 3
1 4 5
2 1 4
Output
6
11
34
23
32

题意:给出n个数,m个操作,操作有两种,分别位更新和询问,操作码位1是更新,将p点的数改为x;操作码位2是查询,给出x到y区间内所有可能(i,j)区间内的异或的和,x<=i<=j<=y;
思路:明显的线段树的题,直接维护异或的前缀和不好查询,所以看到一个很巧妙的做法,将每一个二进制位分别建一个线段树,线段树每个点的信息是改点异或的前缀和,线段树维护前缀和为1的点的数量。
对于(i,j)区间内该位的异或和就是(xi-1^xj)*该位的基数,那么该位总共有多少个值呢?就是(x-1,y)内(0的数量)*(1的数量).
 
    
#include <iostream>
#include <cstdio>
#include <cstring>
#define mod 4001
typedef long long ll;
using namespace std;
const int maxn=1e5+10;

int a[maxn];
struct SegTree{
    struct node{
    int l,r,val,tag;}t[maxn<<2];//val记录异或前缀和1的数量

    #define l(x) l=t[x].l
    #define r(x) r=t[x].r
    #define v(x) t[x].val
    #define sz(x) t[x].r-t[x].l+1
    #define k1 k<<1
    #define k2 k<<1|1

    void pushup(int k)
    {
        t[k].val=t[k1].val+t[k2].val;
    }

    void pushdown(int k)
    {
        if(t[k].tag)
        {
            t[k1].val=sz(k1)-t[k1].val; t[k1].tag^=1;
            t[k2].val=sz(k2)-t[k2].val; t[k2].tag^=1;
            t[k].tag=0;
        }
    }

    void build(int k,int pl,int pr)
    {
        t[k].l=pl,t[k].r=pr;
        t[k].tag=0; t[k].val=0;

        if(pl==pr) return ;
        int mid=(pl+pr)>>1;

        build(k1,pl,mid); build(k2,mid+1,pr);
    }

    void update(int k,int pl,int pr)
    {
        int l,r;
        l=t[k].l; r=t[k].r;
        if(l>=pl&&r<=pr)
        {
            //if(l==2&&r==2) printf("222222:%d:2222222\n",t[k].val);
            t[k].val=sz(k)-t[k].val;
            //if(l==2&&r==2) printf("222222,%d:%d:2222222\n",sz(k),t[k].val);
            t[k].tag^=1;
            return ;
        }
        pushdown(k);
        int mid=(l+r)>>1;

        if(pl<=mid) update(k1,pl,pr);
        if(pr>mid) update(k2,pl,pr);
        pushup(k);
    }

    int query(int k,int pl,int pr)
    {
        int l,r;
        l(k); r(k);

        if(l>=pl&&r<=pr)
        {
            return t[k].val;
        }
        pushdown(k);
        int mid=(l+r)>>1;
        int ans=0;
        if(pl<=mid) ans+=query(k1,pl,pr);
        if(pr>mid) ans+=query(k2,pl,pr);

        return ans;
    }
}seg[12];

int main()
{
    int n,m;

    cin>>n>>m;

    for(int i=0;i<=10;i++) seg[i].build(1,1,n);
    for(int i=1;i<=n;i++)
        {
            scanf("%d",a+i);
            for(int j=0;j<=10;j++)
                {
                    if((a[i]>>j)&1) seg[j].update(1,i,n);
                    /*printf("%d,%d:\n",i,j);
                                    for(int k=1;k<=8;k++)
                {
                    printf("%d:%d %d,%d-%d\n",k,seg[j].t[k].l,seg[j].t[k].r,seg[j].t[k].val,seg[j].t[k].tag);
                }
                printf("-----------end------------\n");*/
                }

        }
    while(m--)
    {
        int op,x,y;
        scanf("%d%d%d",&op,&x,&y);
        if(op==1)
        {
            int tmp=a[x]^y;
            for(int j=0;j<=10;j++)
                {
                    if((tmp>>j)&1) seg[j].update(1,x,n);
                }
            a[x]=y;
        }
        else
        {
            ll ans=0;
            for(int j=0;j<=10;j++)
            {
                ll tmp=seg[j].query(1,x-1,y);
                //cout<<j<<":"<<tmp<<','<<(y-x+2-tmp)<<endl;
                ans=(ans+tmp*(y-x+2-tmp)%mod*(1<<j))%mod;
                //cout<<j<<","<<ans<<endl;
            }
            cout<<ans<<endl;
        }
    }
}
/************
error:13/ 在sz(x) 后加上了;,使得在函数中使用sz(x)会提前结束,导致出错


************/

猜你喜欢

转载自www.cnblogs.com/npunch/p/12316522.html