loj515 「LibreOJ β Round #2」贪心只能过样例[bitset+bool背包]
由于bitset极其不熟练且在实际题目中想不起来运用它来优化,于是练了几道题。
这题是一个分组的bool背包,每组必须选一个,暴力的话是$O(n^5)$。
如果dp数组不要一维滚动的话,有两种枚举方法,一种是枚举体积放外层然后同一组物品放内层,另一种是反过来。
for i 1...n for j 1...V for k 1...a[i] f[i][j]|=f[i-1][j-a[k]] or for i 1...n for k 1...a[i] for j 1...V f[i][j]|=f[i-1][j-a[k]]
然后注意第二种转移有一个可优化的地方。每次$f_{i-1,j}$都是固定向后移$a[k]$位的。这里可以把状态压成一个bitset,可以表出是1,那么整体右移$a[k]$位,取一下或,就是现在可以表出的。是不是很有道理。。于是这个$O(V)\to O(\frac{V}{64})$。
然后这题就可以了。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<cmath> 6 #include<queue> 7 #include<bitset> 8 #define mst(x) memset(x,0,sizeof x) 9 #define dbg(x) cerr << #x << " = " << x <<endl 10 #define dbg2(x,y) cerr<< #x <<" = "<< x <<" "<< #y <<" = "<< y <<endl 11 using namespace std; 12 typedef long long ll; 13 typedef double db; 14 typedef pair<int,int> pii; 15 template<typename T>inline T _min(T A,T B){return A<B?A:B;} 16 template<typename T>inline T _max(T A,T B){return A>B?A:B;} 17 template<typename T>inline char MIN(T&A,T B){return A>B?(A=B,1):0;} 18 template<typename T>inline char MAX(T&A,T B){return A<B?(A=B,1):0;} 19 template<typename T>inline void _swap(T&A,T&B){A^=B^=A^=B;} 20 template<typename T>inline T read(T&x){ 21 x=0;int f=0;char c;while(!isdigit(c=getchar()))if(c=='-')f=1; 22 while(isdigit(c))x=x*10+(c&15),c=getchar();return f?x=-x:x; 23 } 24 const int N=1e6+3; 25 bitset<N> f[2]; 26 int n,l,r,now; 27 28 int main(){//freopen("test.in","r",stdin);//freopen("test.ans","w",stdout); 29 f[0][0]=1; 30 read(n);while(n--){ 31 read(l),read(r);f[now^=1].reset(); 32 for(register int i=l;i<=r;++i)f[now]|=f[now^1]<<(i*i); 33 } 34 printf("%d\n",f[now].count()); 35 return 0; 36 }
总结:bitset优化用途之一:判断每位是否可行,操作的时候可以直接整体修改。