洛谷P3537 [POI2012]SZA-Cloakroom(背包)
蠢了……还以为背包只能用来维护方案数呢……没想到背包这么神奇……
我们用$dp[i]$表示当$c$的和为$i$时,所有的方案中使得最小的$b$最大时最小的$b$是多少
然后把所有的点按照$a$排序,询问按照$m$排序
然后跑一遍背包,如果$dp[q[i].k]>q[i].s+q[i].m$,即存在方案使得$c$的和为$q[i].k$且所有的$b$都大于$q[i].s+q[i].m$,那么这个询问就是可行的
但这个时间复杂度……我实在不明白为什么它能跑出来……而且好像还很快的样子……明明理论上得跑11天才能出答案……
1 //minamoto 2 #include<bits/stdc++.h> 3 #define inf 0x3f3f3f3f 4 using namespace std; 5 #define getc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++) 6 char buf[1<<21],*p1=buf,*p2=buf; 7 template<class T>inline bool cmax(T&a,const T&b){return a<b?a=b,1:0;} 8 inline int read(){ 9 #define num ch-'0' 10 char ch;bool flag=0;int res; 11 while(!isdigit(ch=getc())) 12 (ch=='-')&&(flag=true); 13 for(res=num;isdigit(ch=getc());res=res*10+num); 14 (flag)&&(res=-res); 15 #undef num 16 return res; 17 } 18 const int N=1005,M=1e6+5; 19 struct node{ 20 int a,b,c; 21 inline bool operator <(const node &s)const 22 {return a<s.a;} 23 }p[N]; 24 struct query{ 25 int m,k,s,id; 26 inline bool operator <(const query &b)const 27 {return m<b.m;} 28 }q[M]; 29 int dp[100005],n,m,ans[M]; 30 int main(){ 31 // freopen("testdata.in","r",stdin); 32 n=read(); 33 for(int i=1;i<=n;++i) 34 p[i].c=read(),p[i].a=read(),p[i].b=read(); 35 sort(p+1,p+1+n); 36 m=read(); 37 for(int i=1;i<=m;++i) 38 q[i].m=read(),q[i].k=read(),q[i].s=read(),q[i].id=i; 39 sort(q+1,q+1+m);dp[0]=inf; 40 for(int i=1,j=1;i<=m;++i){ 41 while(j<=n&&p[j].a<=q[i].m){ 42 for(int k=100000;k>=p[j].c;--k) 43 cmax(dp[k],min(dp[k-p[j].c],p[j].b)); 44 ++j; 45 } 46 ans[q[i].id]=dp[q[i].k]>q[i].m+q[i].s; 47 } 48 for(int i=1;i<=m;++i) puts(ans[i]?"TAK":"NIE"); 49 return 0; 50 }
深深地明白自己的弱小