BZOJ2794 : [Poi2012]Cloakroom

考虑离线,将物品和询问都按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;
}

  

posted @ 2015-08-03 00:37  Claris  阅读(326)  评论(0编辑  收藏  举报