考慮離線,將物品和詢問都按a從小到大排序。
然後對於當前處理的詢問,將所有a不超過它的物品都加入揹包中。
設f[i]表示和為i時min(b)的最大值,若f[k]>m+s,則TAK。
時間複雜度$O(q\log q+nk)$。
#include<cstdio> #include<algorithm> const int N=1000010,M=100000; int n,m,i,j,k,f[M+1];bool ans[N]; struct P{int a,b,c,p;}a[1010],b[N]; inline bool cmp(P a,P b){return a.a<b.a;} inline int min(int a,int b){return a<b?a:b;} inline void up(int&a,int b){if(a<b)a=b;} inline void read(int&a){char c;while(!(((c=getchar())>='0')&&(c<='9')));a=c-'0';while(((c=getchar())>='0')&&(c<='9'))(a*=10)+=c-'0';} int main(){ for(read(n),i=1;i<=n;i++)read(a[i].c),read(a[i].a),read(a[i].b); for(read(m),i=1;i<=m;i++)read(b[i].a),read(b[i].c),read(b[i].b),b[i].b+=b[i].a,b[i].p=i; for(std::sort(a+1,a+n+1,cmp),std::sort(b+1,b+m+1,cmp),f[0]=2000000001,i=j=1;i<=m;i++){ for(;j<=n&&a[j].a<=b[i].a;j++)for(k=M;k>=a[j].c;k--)up(f[k],min(f[k-a[j].c],a[j].b)); ans[b[i].p]=f[b[i].c]>b[i].b; } for(i=1;i<=m;i++)puts(ans[i]?"TAK":"NIE"); return 0; }