( ext{Description})
( ext{Solution})
(30 ext{pts}) 就是 (01) 背包。
发现我们的瓶颈就是容量要开到 (1e6),但其实如果随机一下数据是很难出现这种情况的(我们把正容量和负容量打乱)。因为我们每件物品的容量较小,而且打乱后出现很长一段是正容量,后面是负容量的“山峰”概率很小(最后要保证回到 (0) 值)。
所以设定一个可以接受的容量,超出的认为它不行就行了。
好玄学。
( ext{Code})
#include <cstdio>
#define rep(i,_l,_r) for(signed i=(_l),_end=(_r);i<=_end;++i)
#define print(x,y) write(x),putchar(y)
typedef long long ll;
void write(ll x) {
if(x<0) return (void)(putchar('-'),write(-x));
if(x>9) write(x/10);
putchar(x%10^48);
}
int read() {
int x=0,f=1; char s;
while((s=getchar())>'9'||s<'0') if(s=='-') f=-1;
while(s>='0'&&s<='9') x=(x<<1)+(x<<3)+(s^48),s=getchar();
return x*f;
}
//C(25,12)=5200300
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn=1005,lim=1e5;
const ll inf=(1ll<<50);
int n,m;
ll f[lim+5],ans;
struct node {
int w,v;
} s[maxn<<1];
int main() {
//freopen("game.in","r",stdin); freopen("game.out","w",stdout);
n=read(),m=read(); srand(20201121);
rep(i,1,n+m) {
s[i].w=read(),s[i].v=read();
if(i>n) s[i].w=-s[i].w;
}
random_shuffle(s+1,s+n+m+1);
rep(i,0,lim) f[i]=-inf;
f[lim>>1]=0;
rep(i,1,n+m+1)
if(s[i].w>=0) {
for(int j=lim;j>=s[i].w;--j)
if(f[j-s[i].w]!=-inf) f[j]=max(f[j],f[j-s[i].w]+s[i].v);
}
else {
rep(j,0,s[i].w+lim)
if(f[j-s[i].w]!=-inf) f[j]=max(f[j],f[j-s[i].w]+s[i].v);
}
print(f[lim>>1],'
');
return 0;
}