洛谷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 }
原文地址:https://www.cnblogs.com/bztMinamoto/p/9786718.html