题目描述:
题目分析:
和恰好为k可以用背包。
物品a[i]<=m的限制可以将询问离线后排序添加物品。
但是b[i]>m+s就不好搞了。
这里有一个神奇的trick:
f
[
i
]
f[i]
f[i]记录组成和为
i
i
i的物品中最小
b
b
b的最大值,这个若最大值>m+s,则说明存在一种方案。初始
f
[
0
]
=
I
N
F
f[0]=INF
f[0]=INF,
f
[
i
>
0
]
=
0
f[i>0]=0
f[i>0]=0,转移即为
f
[
i
]
=
max
j
(
min
(
f
[
i
−
c
j
]
,
b
j
)
)
f[i]=\max_j(\min(f[i-c_j],b_j))
f[i]=maxj(min(f[i−cj],bj))
这提醒我们不等式可以转化为最值问题从而解决一维偏序。
Code:
#include<bits/stdc++.h>
#define maxn 1005
using namespace std;
char cb[1<<18],*cs,*ct;
#define getc() (cs==ct&&(ct=(cs=cb)+fread(cb,1,1<<18,stdin),cs==ct)?0:*cs++)
inline void read(int &a){
char c;while(!isdigit(c=getc()));
for(a=c-'0';isdigit(c=getc());a=a*10+c-'0');
}
int n,m,K,f[100005];
bool ans[1000005];
struct node{
int x,y,v,id;
bool operator < (const node &p)const{return x<p.x;}
}A[1005],q[1000005];
int main()
{
read(n);
for(int i=1;i<=n;i++) read(A[i].v),read(A[i].x),read(A[i].y);
sort(A+1,A+1+n);
read(m);
for(int i=1;i<=m;i++) read(q[i].x),read(q[i].v),read(q[i].y),q[i].y+=q[i].x,K=max(K,q[i].v),q[i].id=i;
sort(q+1,q+1+m);
f[0]=2e9;
for(int i=1,j=1;i<=m;i++){
while(j<=n&&A[j].x<=q[i].x){
for(int k=K;k>=A[j].v;k--) f[k]=max(f[k],min(f[k-A[j].v],A[j].y));
j++;
}
ans[q[i].id]=f[q[i].v]>q[i].y;
}
for(int i=1;i<=m;i++) puts(ans[i]?"TAK":"NIE");
}