题意:带修改地维护区间异或和
思路:带修改莫队(注意分块大小为 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;
}