loj515 「LibreOJ β Round #2」贪心只能过样例[bitset+bool背包]

时间:2023-03-10 07:11:36
loj515 「LibreOJ β Round #2」贪心只能过样例[bitset+bool背包]

由于bitset极其不熟练且在实际题目中想不起来运用它来优化,于是练了几道题。

这题是一个分组的bool背包,每组必须选一个,暴力的话是$O(n^5)$。

如果dp数组不要一维滚动的话,有两种枚举方法,一种是枚举体积放外层然后同一组物品放内层,另一种是反过来。

for i ...n
for j ...V
for k ...a[i]
f[i][j]|=f[i-][j-a[k]]
or
for i ...n
for k ...a[i]
for j ...V
f[i][j]|=f[i-][j-a[k]]

然后注意第二种转移有一个可优化的地方。每次$f_{i-1,j}$都是固定向后移$a[k]$位的。这里可以把状态压成一个bitset,可以表出是1,那么整体右移$a[k]$位,取一下或,就是现在可以表出的。是不是很有道理。。于是这个$O(V)\to O(\frac{V}{64})$。

然后这题就可以了。

 #include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
#include<bitset>
#define mst(x) memset(x,0,sizeof x)
#define dbg(x) cerr << #x << " = " << x <<endl
#define dbg2(x,y) cerr<< #x <<" = "<< x <<" "<< #y <<" = "<< y <<endl
using namespace std;
typedef long long ll;
typedef double db;
typedef pair<int,int> pii;
template<typename T>inline T _min(T A,T B){return A<B?A:B;}
template<typename T>inline T _max(T A,T B){return A>B?A:B;}
template<typename T>inline char MIN(T&A,T B){return A>B?(A=B,):;}
template<typename T>inline char MAX(T&A,T B){return A<B?(A=B,):;}
template<typename T>inline void _swap(T&A,T&B){A^=B^=A^=B;}
template<typename T>inline T read(T&x){
x=;int f=;char c;while(!isdigit(c=getchar()))if(c=='-')f=;
while(isdigit(c))x=x*+(c&),c=getchar();return f?x=-x:x;
}
const int N=1e6+;
bitset<N> f[];
int n,l,r,now; int main(){//freopen("test.in","r",stdin);//freopen("test.ans","w",stdout);
f[][]=;
read(n);while(n--){
read(l),read(r);f[now^=].reset();
for(register int i=l;i<=r;++i)f[now]|=f[now^]<<(i*i);
}
printf("%d\n",f[now].count());
return ;
}

总结:bitset优化用途之一:判断每位是否可行,操作的时候可以直接整体修改。