2019icpc南昌邀請賽F(線段樹)

題目連接:https://nanti.jisuanke.com/t/40258node

題意:給長爲n的數組a,有m次操做,包括單點修改和查詢F(l,r),其值爲全部f(i,j)的異或和,l<=i<=j<=r,即數組

其中ui

(n,m<=1e5).spa

思路:這種題能夠用線段樹來進行修改和查詢,但須要先化簡。對於l<=x<=r,包括ax的區間有(r-x+1)*(x-l+1)個,注意到當區間長爲偶數時,改值恆爲偶數,那麼也就是說ax出現偶數次,那麼查詢結果爲0。當區間長度爲奇數時,若x與l奇偶性不一樣,則該值爲偶數,異或值爲0; 若奇偶值相同,則該值爲奇數,異或值爲ax,故須要用線段樹維護與l奇偶性相同的元素的異或和。code

   可是合併兩個區間的時候,可能出現右區間的l與左區間的l奇偶性不一樣的狀況,這時,右區間維護的值不能直接求與。須要同右區間總體異或和異或以後獲得與左區間的l奇偶性相同的那些元素的異或和。說的很繞,手動算一下就明白,因此咱們還須要用線段樹維護區間的異或和。blog

AC代碼:it

#include<cstdio>
#include<algorithm>
using namespace std;

const int maxn=100005;

int T,n,m,cas,a[maxn];

struct node{
    int l,r;
    int sum,val;
}tr[maxn<<2];

void pushup(int v){
    tr[v].sum=tr[v<<1].sum^tr[v<<1|1].sum;
    if((tr[v<<1|1].l-tr[v].l)%2==0)
        tr[v].val=tr[v<<1].val^tr[v<<1|1].val;
    else
        tr[v].val=tr[v<<1].val^(tr[v<<1|1].sum^tr[v<<1|1].val);
}

void build(int v,int l,int r){
    tr[v].l=l,tr[v].r=r;
    if(l==r){
        tr[v].sum=tr[v].val=a[l];
        return;
    }
    int mid=(l+r)>>1;
    build(v<<1,l,mid);
    build(v<<1|1,mid+1,r);
    pushup(v);
}

void update(int v,int x,int y){
    if(tr[v].l==tr[v].r){
        tr[v].sum=tr[v].val=y;
        return;
    }
    int mid=(tr[v].l+tr[v].r)>>1;
    if(x<=mid) update(v<<1,x,y);
    else update(v<<1|1,x,y);
    pushup(v);
}

void query(int v,int l,int r,int& x,int& y){
    if(tr[v].l==l&&tr[v].r==r){
        x=tr[v].val;
        y=tr[v].sum;
        return;
    }    
    int mid=(tr[v].l+tr[v].r)>>1;
    if(r<=mid)
        query(v<<1,l,r,x,y);
    else if(l>mid)
        query(v<<1|1,l,r,x,y);
    else{
        int a,b,c,d;
        query(v<<1,l,mid,a,b);
        query(v<<1|1,mid+1,r,c,d);
        if((tr[v<<1|1].l-l)%2==0)
            x=a^c,y=b^d;
        else
            x=a^(d^c),y=b^d;
    }
}

int main(){
    scanf("%d",&T);
    while(T--){
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;++i)
            scanf("%d",&a[i]);
        build(1,1,n);
        printf("Case #%d:\n",++cas);
        while(m--){
            int op,x,y;
            scanf("%d%d%d",&op,&x,&y);
            if(op==0)
                update(1,x,y);
            else{
                if((y-x+1)%2==0)
                    printf("0\n");
                else{
                    int a,b;
                    query(1,x,y,a,b);
                    printf("%d\n",a);
                }
            }
        }
    }
    return 0;
}
相關文章
相關標籤/搜索