CF 400E Inna and Binary Logic(多维线段树)

来源:互联网 发布:windows内存占用高 编辑:程序博客网 时间:2024/05/18 22:17

Inna is fed up with jokes about female logic. So she started using binary logic instead.

Inna has an array of n elements a1[1], a1[2], ..., a1[n]. Girl likes to train in her binary logic, so she does an exercise consisting of nstages: on the first stage Inna writes out all numbers from array a1, on the i-th (i ≥ 2) stage girl writes all elements of array ai, which consists of n - i + 1 integers; the k-th integer of array ai is defined as follows: ai[k] = ai - 1[kAND ai - 1[k + 1]. Here AND is bit-wise binary logical operation.

Dima decided to check Inna's skill. He asks Inna to change array, perform the exercise and say the sum of all  elements she wrote out during the current exercise.

Help Inna to answer the questions!

Input

The first line contains two integers n and m (1 ≤ n, m ≤ 105) — size of array a1 and number of Dima's questions. Next line contains nintegers a1[1], a1[2], ..., a1[n] (0 ≤ ai ≤ 105) — initial array elements.

Each of next m lines contains two integers — Dima's question description. Each question consists of two integers pi, vi(1 ≤ pi ≤ n; 0 ≤ vi ≤ 105). For this question Inna should make a1[pi] equals vi, and then perform the exercise. Please, note that changes are saved from question to question.

Output

For each question print Inna's answer on a single line.

Sample test(s)
input
3 41 1 11 12 23 21 2
output
64712
分析:给你a1[i],构造如下ai[k]=ai-1[k]&ai-1[k+1]
我们一位一位的考虑设某位连续的1的个数为x,那么
对答案贡献为(x+x-1+x-2...+1)=(x+1)*x/2所以建立18棵线段树计算每位的
贡献即可
#include<cstdio>#include<cstring>#include<algorithm>#include<vector>#include<string>#include<iostream>#include<queue>#include<cmath>#include<map>#include<stack>#include<set>using namespace std;#define REPF( i , a , b ) for ( int i = a ; i <= b ; ++ i )#define REP( i , n ) for ( int i = 0 ; i < n ; ++ i )#define CLEAR( a , x ) memset ( a , x , sizeof a )const int INF=0x3f3f3f3f;typedef long long LL;const int maxn=1e5+100;int n,m;int A[maxn];struct Tree{    LL sum[maxn<<2];    int lmax[maxn<<2],rmax[maxn<<2],o;    void pushup(int rs,int s)    {        lmax[rs]=lmax[rs<<1];        if(lmax[rs<<1]==(s-(s>>1)))            lmax[rs]+=lmax[rs<<1|1];        rmax[rs]=rmax[rs<<1|1];        if(rmax[rs]==(s>>1))            rmax[rs]+=rmax[rs<<1];        sum[rs]=sum[rs<<1]+sum[rs<<1|1];        if(rmax[rs<<1]&&lmax[rs<<1|1])        {            LL x=rmax[rs<<1];            sum[rs]-=(x+1)*x/2;            LL y=lmax[rs<<1|1];            sum[rs]-=(y+1)*y/2;            LL xy=rmax[rs<<1]+lmax[rs<<1|1];            sum[rs]+=(xy+1)*xy/2;        }    }    void build(int l,int r,int rs)    {        if(l==r)        {            sum[rs]=lmax[rs]=rmax[rs]=(A[l]&(1<<o)?1:0);            return ;        }        int mid=(l+r)>>1;        build(l,mid,rs<<1);        build(mid+1,r,rs<<1|1);        pushup(rs,r-l+1);    }    void update(int x,int c,int l,int r,int rs)    {        if(l==r)        {            sum[rs]=lmax[rs]=rmax[rs]=(c&(1<<o)?1:0);            return;        }        int mid=(l+r)>>1;        if(x<=mid) update(x,c,l,mid,rs<<1);        else update(x,c,mid+1,r,rs<<1|1);        pushup(rs,r-l+1);    }}t[18];int main(){    int x,y;    while(~scanf("%d%d",&n,&m))    {        REPF(i,1,n)          scanf("%d",&A[i]);        for(int i=0;i<18;i++)        {            t[i].o=i;            t[i].build(1,n,1);        }        while(m--)        {            scanf("%d%d",&x,&y);            LL S=0;            for(int i=0;i<18;i++)            {                t[i].update(x,y,1,n,1);                S+=(1LL<<i)*t[i].sum[1];                //cout<<"fuck  "<<n<<endl;                //cout<<"fuck  "<<t[i].sum[1]<<endl;            }            printf("%I64d\n",S);        }    }    return 0;}/*3 41 1 11 12 23 21 2*/


0 0
原创粉丝点击