【NOIP2016提高A組模擬8.17】(雅禮聯考day1)Binary
阿新 • • 發佈:2018-05-16
cstring names 分享圖片 img ace queue lin print mat
題目
分析
首先每個數對\(2^i\)取模。也就是把每個數的第i位以後刪去。
把它們放進樹狀數組裏面。
那麽當查詢操作,
答案就位於區間\([2^i-x,2^{i-1}-1-x]\)中,直接查詢就可以了。
細節很多,註意處理。
#include <cmath> #include <iostream> #include <cstdio> #include <cstdlib> #include <cstring> #include <algorithm> #include <queue> const long long maxlongint=2147483647; const long long mo=1000000007; const long long N=100005; using namespace std; long long tree[N*11][25]; long long a[N],n,q,mi[25]; int twobird(int x) { return x&(-x); } int insert(long long k,int j) { k++; while(k<=mi[20]) { tree[k][j]+=1; k+=twobird(k); } } int delete1(long long k,int j) { k++; while(k<=mi[20]) { tree[k][j]-=1; k+=twobird(k); } } int find(long long k,int j) { k++; int sum=0; while(k>=1) { sum+=tree[k][j]; k-=twobird(k); } return sum; } int main() { mi[0]=1; for(int i=1;i<=22;i++) mi[i]=mi[i-1]*2; scanf("%lld%lld",&n,&q); for(long long i=1;i<=n;i++) { scanf("%lld",&a[i]); for(int j=20;j>=0;j--) insert(a[i]%mi[j],j); } for(int i=1;i<=q;i++) { long long opt,x,y; scanf("%lld%lld%lld",&opt,&x,&y); if(opt==1) { for(int j=20;j>=0;j--) delete1(a[x]%mi[j],j); a[x]=y; for(int j=20;j>=0;j--) insert(a[x]%mi[j],j); } else { long long ans=0; for(int j=20;j>=0;j--) { if(y-mi[j]>=0) { long long x1=((mi[j]-x)%mi[j+1]+mi[j+1])%mi[j+1],x2=((mi[j+1]-x-1)%mi[j+1]+mi[j+1])%mi[j+1]; if(x1<=x2) ans+=(find(x2,j+1)-find(x1-1,j+1))*mi[j]; else { ans+=(find(mi[j+1]-1,j+1)-find(x1-1,j+1)+find(x2,j+1))*mi[j]; } y-=mi[j]; } } printf("%lld\n",ans); } } }
【NOIP2016提高A組模擬8.17】(雅禮聯考day1)Binary