hdu 6610 Game

 题意:带修改地维护区间异或和

思路:带修改莫队(注意分块大小为 0.66666n)

#include <bits/stdc++.h>
using namespace std;
typedef int lint;
typedef long long LL;
const lint maxn = 1000005;
lint a[maxn],pos[maxn],sum[maxn];
LL ans[maxn];
lint block;
struct query{
    lint l,r,k,id;
    query( lint ll = 0,lint rr = 0,lint kk = 0,lint idid = 0 ){
        l = ll; r = rr;k = kk;id = idid;
    }
    bool operator < ( const query & b )const{
        if( l/block == b.l/block ){
            if( r/block == b.r/block ){
                return k < b.k;
            }
            return r < b.r ;
        }
        return l < b.l;
    }
};
vector<query> ve;
LL cnt[maxn],ccnt;
void init(lint n){
    block = floor(pow(n,0.6666666));
    memset( cnt,0,sizeof(cnt) );
    ccnt = 0;
}
void update( lint v,lint f ){
    if( f == 1 ){
        ccnt += cnt[v];
        cnt[v]++;
    }else{
        cnt[v]--;
        ccnt -= cnt[v];
    }
}
void up( lint L,lint R,lint tim ){
    lint p = pos[tim];
    if( p >= L && p <= R ){
        cnt[ sum[p] ]--;
        ccnt -= cnt[ sum[p] ];
        swap( a[p],a[p+1] );
        sum[p] = sum[p-1]^a[p];
        ccnt += cnt[ sum[p] ];
        cnt[ sum[p] ]++;
    }else{
        swap( a[p],a[p+1] );
        sum[p] = sum[p-1]^a[p];
    }
}
void solve(){
    lint L = 0,R = -1,TIM = 0;
    for( lint i = 0;i < ve.size();i++ ){
        lint tim = ve[i].k;
        lint l = ve[i].l;
        lint r = ve[i].r;
        while( TIM > tim ) {
            up( L,R,TIM-- );
        }
        while( TIM < tim ){
            up( L,R,++TIM );
        }
        while( R < r ) update( sum[++R],1 );
        while( l < L ) update( sum[--L],1 );
        while( R > r ) update( sum[R--],-1 );
        while( l > L ) update( sum[L++],-1 );
        ans[ ve[i].id ] = (LL)(r - l)*(r-l+1)/2-ccnt;
    }
}
int main() {
    lint n,m;
    while( 2 == scanf("%d%d",&n,&m) ){
        init(n);
        ve.clear();
        lint  id = 0,tim = 0;
        for( lint i  = 1;i <= n;i++ ) {
            scanf("%d",&a[i]);
            sum[i] = sum[i-1]^a[i];
        }
        for( lint i = 1;i <= m;i++ ){
            lint op;
            scanf("%d",&op);
            if( op == 1 ){
                id++;
                lint l,r;
                scanf("%d%d",&l,&r);
                l--;
                //cout << id << endl;
                ve.push_back( query( l,r,tim,id ) );
            }else{
                lint p;
                scanf("%d",&p);
                tim++;
                pos[tim] = p;
            }
        }
        sort( ve.begin(),ve.end() );
        solve();
        for( lint i = 1;i <= id;i++ ){
            printf("%lld\n",ans[i]);
        }
    }
    return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值