2794: [Poi2012]Cloakroom

2794: [Poi2012]Cloakroom

Time Limit: 20 Sec   Memory Limit: 128 MB
Submit: 231   Solved: 155
[ 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

Source

[ Submit][ Status][ Discuss]

将询问看作,考虑所有a <= m的物品,用他们凑成c的和为k的情况下,最小的b的最大值是多少
如果这个值大于m + s,说明有解,否则无解
那么,将询问按照m升序,物品按照a升序排好,剩下的就是普通的背包问题了
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<vector>
#include<queue>
#include<set>
#include<map>
#include<stack>
#include<bitset>
#include<ext/pb_ds/priority_queue.hpp>
using namespace std;

const int maxn = 1E3 + 10;
const int maxm = 1E6 + 10;
const int N = 100001;

struct data{
	int a,b,c; data(){}
	data(int a,int b,int c): a(a),b(b),c(c){}
	bool operator < (const data &B) const {return a < B.a;}
}D[maxn];

struct Query{
	int m,k,s,Num; Query(){}
	Query(int m,int k,int s,int Num): 
		m(m),k(k),s(s),Num(Num){}
	bool operator < (const Query &B) const {return m < B.m;}
}Q[maxm];

int n,m,Max,f[N];
bool Ans[maxm];

void Insert(int g)
{
	for (int i = Max; i >= D[g].c; i--)
		if (f[i - D[g].c]) f[i] = max(f[i],min(f[i - D[g].c],D[g].b));
}

int getint()
{
	char ch = getchar(); int ret = 0;
	while (ch < '0' || '9' < ch) ch = getchar();
	while ('0' <= ch && ch <= '9')
		ret = ret*10 + ch - '0',ch = getchar();
	return ret;
}

int main()
{
	#ifdef DMC
		freopen("DMC.txt","r",stdin);
	#endif
	
	n = getint();
	for (int i = 1; i <= n; i++)
	{
		int c = getint(),a,b;
		a = getint(); b = getint();
		D[i] = data(a,b,c);
	}
	sort(D + 1,D + n + 1);
	m = getint();
	for (int i = 1; i <= m; i++)
	{
		int m = getint(),k,s;
		k = getint(); s = getint();
		Q[i] = Query(m,k,s,i);
		Max = max(Max,k);
	}
	sort(Q + 1,Q + m + 1);
	
	int now = 1; f[0] = ~0U>>1;
	for (int i = 1; i <= m; i++)
	{
		while (now <= n && Q[i].m >= D[now].a) Insert(now++);
		Ans[Q[i].Num] = f[Q[i].k] > Q[i].m + Q[i].s ? 1 : 0;
	}
	for (int i = 1; i <= m; i++)
		if (Ans[i]) puts("TAK"); else puts("NIE");
	return 0;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值