题目大意
Data Constraint
n,q≤105,ai<220
题解
和SCOI2016的题目有相似之处。
每一位开一个树状数组,以数轴为轴,记录只保留当前位往后的数有哪些。
对于每个询问,我们按位来统计答案,第
k
位对答案的贡献就是
这个怎么查询呢?设当前统计第k位,之前的位置我们不需要考虑。注意到在没有+x的情况下,我们要求的数的下界是
L=k10000...
最高位的1是第
k
位的,上界是
SRC
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std ;
#define N 100000 + 10
#define M 1200000 + 10
typedef long long ll ;
const int Maxv = 1048576 ;
int T[20][M] ;
int a[N] ;
int n , Q ;
int ret ;
ll ans ;
int lowbit( int x ) { return x & (-x) ; }
void Modify( int t , int k , int del ) {
while ( k <= Maxv + 1 ) {
T[t][k] += del ;
k += lowbit(k) ;
}
}
int Find( int t , int k ) {
int ret = 0 ;
if ( k > Maxv ) k = Maxv ;
while ( k > 0 ) {
ret += T[t][k] ;
k -= lowbit(k) ;
}
return ret ;
}
int main() {
scanf( "%d%d" , &n , &Q ) ;
for (int i = 1 ; i <= n ; i ++ ) {
scanf( "%d" , &a[i] ) ;
for (int k = 0 ; k <= 19 ; k ++ ) {
int t = (a[i] & ((1 << (k+1)) - 1)) ;
Modify( k , t + 1 , 1 ) ;
}
}
for (int i = 1 ; i <= Q ; i ++ ) {
int op , x , y ;
scanf( "%d%d%d" , &op , &x , &y ) ;
if ( op == 1 ) {
for (int k = 0 ; k <= 19 ; k ++ ) {
int t = (a[x] & ((1 << (k+1)) - 1)) ;
Modify( k , t + 1 , -1 ) ;
}
a[x] = y ;
for (int k = 0 ; k <= 19 ; k ++ ) {
int t = (a[x] & ((1 << (k+1)) - 1)) ;
Modify( k , t + 1 , 1 ) ;
}
} else {
ans = 0 ;
for (int k = 19 ; k >= 0 ; k -- ) {
if ( !((y >> k) & 1) ) continue ;
int tp = (x & ((1 << (k+1)) - 1)) ;
int L = (1 << k) - tp ;
int R = (1 << (k+1)) - 1 - tp ;
ret = Find( k , R+1 ) - Find( k , L ) ;
L = ((1 << k) | (1 << (k+1))) - tp ;
R = (1 << (k+2)) - 1 - tp ;
ret += Find( k , R+1 ) - Find( k , L ) ;
ans += (ll)ret * (1ll << k) ;
}
printf( "%lld\n" , ans ) ;
}
}
return 0 ;
}
以上.