BZOJ 2794 [Poi2012]Cloakroom(离线+背包)

2794: [Poi2012]Cloakroom

Time Limit: 20 Sec  Memory Limit: 128 MB
Submit: 406  Solved: 241
[Submit][Status][Discuss]

Description

有n件物品,每件物品有三个属性a[i], b[i], c[i] (a[i]<b[i])。
再给出q个询问,每个询问由非负整数m, k, s组成,问是否能够选出某些物品使得:
1. 对于每个选的物品i,满足a[i]<=m且b[i]>m+s。
2. 所有选出物品的c[i]的和正好是k。

Input

第一行一个正整数n (n<=1,000),接下来n行每行三个正整数,分别表示c[i], a[i], b[i] (c[i]<=1,000, 1<=a[i]<b[i]<=10^9)。
下面一行一个正整数q (q<=1,000,000),接下来q行每行三个非负整数m, k, s (1<=m<=10^9, 1<=k<=100,000, 0<=s<=10^9)。

Output


输出q行,每行为TAK (yes)或NIE (no),第i行对应第i此询问的答案。

Sample Input

5

6 2 7

5 4 9

1 2 4

2 5 8

1 3 9

5

2 7 1

2 7 2

3 2 0

5 7 2

4 1 5

Sample Output

TAK

NIE

TAK

TAK

NIE

HINT

题解

这题还行。

看了一会,自信满满,然后就死了。

离线把询问按s排序。把每一个物品按a[i]排序。

然后dp[i]代表当c的和能凑成i时所用的物品b的最小值的最大值。

因为排序后每一个物品只需计算一次,所以复杂度没有飞。(但至少我看来有问题)

所以对于每一个询问,只需判断dp[k]是否大于m+s就行了。

 1 #include<iostream>
 2 #include<cstring>
 3 #include<cstdio>
 4 #include<cmath>
 5 #include<algorithm>
 6 using namespace std;
 7 struct thing{
 8     int c,a,b;
 9 }g[2000];
10 struct query{
11     int l,r,k,id;
12 }q[1000100];
13 int n,t,dp[100100],ans[1000100],mx;
14 bool cmp(thing a,thing b){
15     return a.a<b.a;
16 }
17 bool mmp(query a,query b){
18     return a.l<b.l;
19 }
20 int main(){
21     scanf("%d",&n);
22     for(int i=1;i<=n;i++){
23         scanf("%d%d%d",&g[i].c,&g[i].a,&g[i].b);
24     }
25     scanf("%d",&t);
26     for(int i=1;i<=t;i++){
27         int s,k,m;
28         scanf("%d%d%d",&s,&k,&m);
29         q[i].l=s;
30         q[i].r=s+m;
31         q[i].k=k;
32         q[i].id=i;
33         mx=max(mx,k);
34     }
35     sort(g+1,g+1+n,cmp);
36     sort(q+1,q+1+t,mmp);
37     dp[0]=1999999999;
38     for(int i=1,now=1;i<=t;i++){
39         while(now<=n&&g[now].a<=q[i].l){
40             for(int j=mx;j>=g[now].c;j--){
41                 dp[j]=max(dp[j],min(dp[j-g[now].c],g[now].b));
42             }
43             now++;
44         }
45         ans[q[i].id]=(q[i].r<dp[q[i].k]);
46     }
47     for(int i=1;i<=t;i++){
48         if(ans[i])printf("TAK\n");
49         else printf("NIE\n");
50     }
51     return 0;
52 } 

 

posted @ 2018-09-04 20:58  Xu-daxia  阅读(124)  评论(0编辑  收藏  举报