11.3清北集訓_subset分塊思想
阿新 • • 發佈:2018-11-08
solution
- 我們發現2^16=65536 * 1e5就炸了
- 但是2^8=256,再乘上1e5就不怕了
- 我們發現a&s=a,把a拆成前8位和後8位 和16位一起算是一樣的
- 所以我們搞一個f[pre][suf]表示i^pre=i 且 i=suf 的個數
- add和del時列舉前8位加減
- cnt時列舉後8位
code
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<cstdlib> #include<cmath> using namespace std; inline int read(){ char ch=' ';int f=1;int x=0; while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=getchar();} while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar(); return x*f; } const int N=255;// 2^8-1 int digit[2333][2333]; int main() { freopen("subset.in","r",stdin); freopen("subset.out","w",stdout); int n; n=read(); int i,j,k; char op[10]; int x; for(j=1;j<=n;j++) { scanf("%s",op); x=read(); int l=x>>8;int r=x&(N);int f=0; if(op[0]=='d') f=-1; else if(op[0]=='a') f=1; if(op[0]=='a'||op[0]=='d') { for(i=0;i<=N;i++) { if((l&i)==l) { digit[i][r]+=f; } } } else { int ans=0; for(i=0;i<=N;i++) { if((i&r)==i) { ans+=digit[l][i]; } } printf("%d\n",ans); } } return 0; }