BZOJ2794/POI2012 Cloakroom
来源:互联网 发布:php写web会员登录 编辑:程序博客网 时间:2024/05/14 10:04
Task
有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。
n<=1,000, q<=1,000,000.
c[i]<=1,000, 1<=a[i]<b[i]<=10^9
1<=m<=10^9, 1<=k<=100,000, 0<=s<=10^9
Solution
离线.
把询问和节点都根据左端点排序,保证询问[l,r]时,所有考虑的物品的左端点都满足条件.满足左端点的物品个数是不断增加的,一旦满足,接下来所有询问都会满足.那么现在只用考虑右端点了.
直接确定所有物品再进行01背包肯定不行.那么考虑新思路.假如因为现在可选物品的范围一直增大,我们可以对当前物品的信息进行记录.由于k并不大,可以考虑把k存入下标:
设dp[x]为当前价值构成x最远的b[i].
对于询问可以直接判断dp[k]与m+s的关系,
对于更新,用01背包进行更新即可.
题外话:
这道题的思路来源于BestCoder round#86 1005(hdu5808,题解戳这,题目链接戳这)的思路,都是询问一些符合范围的物品价值是否能够达到k.而且思路也是相近的,只不过BC的这道题信息多一维,用了分治来优化,思路更复杂一些.
#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>#include<vector>#define ll long long#include<queue>#include<set>using namespace std;inline void rd(int &res){ res=0;char c; while(c=getchar(),c<48); do res=(res<<1)+(res<<3)+(c^48); while(c=getchar(),c>=48);}inline void print(ll x){ if(!x)return ; print(x/10); putchar((x%10)^48);}inline void sc(ll x){ if(x<0){x=-x;putchar('-');} print(x); if(!x)putchar('0'); putchar('\n');}inline void Max(int &x,int y){if(x<y)x=y;}inline void Min(int &x,int y){if(x>y)x=y;}const int M=1005;const int N=1e6+5;const int P=100000;int dp[P+5],n,m,ans[N];char s[2][3];struct node{ int l,r,v,id; node(){id=-1;} bool operator<(const node &tmp)const{ if(l!=tmp.l)return l<tmp.l; return id<tmp.id; }}A[M+N];void pt(int c){ for(int i=0;i<3;i++)putchar(s[c][i]); putchar('\n');}int main(){ int n,i,j,mx=0,sum=0,cas,a,b,k; memset(dp,-1,sizeof(dp)); rd(n); s[0][0]='N',s[0][1]='I',s[0][2]='E'; s[1][0]='T',s[1][1]='A',s[1][2]='K'; for(i=1;i<=n;i++){ rd(A[i].v);rd(A[i].l);rd(A[i].r); Max(mx,A[i].r); } rd(m); for(i=1;i<=m;i++){ rd(A[i+n].l);rd(A[i+n].v);rd(A[i+n].r); A[i+n].r+=A[i+n].l; A[i+n].id=i; } sort(A+1,A+1+n+m); dp[0]=mx+1; for(i=1;i<=n+m;i++){ int l=A[i].l,r=A[i].r,v=A[i].v,id=A[i].id; if(~id){//询问 if(~dp[v]&&dp[v]>r)ans[id]=1; else ans[id]=0; continue; }//update (j+v)<=P j<=P-v for(j=min(P-v,sum);j>=0;j--){ if(~dp[j])Max(dp[v+j],min(dp[j],r));//更新dp值 } sum+=v; } for(i=1;i<=m;i++)pt(ans[i]); return 0;}
1 0
- BZOJ2794: [Poi2012]Cloakroom
- BZOJ2794 [Poi2012]Cloakroom
- BZOJ2794/POI2012 Cloakroom
- BZOJ2794: [Poi2012]Cloakroom
- bzoj2794 [Poi2012]Cloakroom ( 背包DP+离线 )
- 2794: [Poi2012]Cloakroom
- bzoj 2794 [Poi2012]Cloakroom dp
- BZOJ 2794: [Poi2012]Cloakroom 背包DP
- BZOJ 2794: [Poi2012]Cloakroom 询问离线 背包dp
- [POI 2012]Cloakroom(DP)
- POI2012题解
- [Poi2012]Festival
- BZOJ 2789: [Poi2012]Letters
- BZOJ2793 [Poi2012]Vouchers 调和级数
- [BZOJ 2790]POI2012 Distance
- [BZOJ 2789]POI2012 Letters
- [BZOJ 2791]POI2012 Rendezvous
- [BZOJ 2803]Poi2012 Prefixuffix
- 剑指Offer面试题37(Java版):两个链表的第一个公共结点
- contiki概述
- Chapter 2 匹配边界及选择
- 全卷积网络(FCN)
- Contiki学习——HelloWorld
- BZOJ2794/POI2012 Cloakroom
- hdu5918Sequence I+KMP
- 练习
- 笔试面试总结
- Chapter 3 正则表达式的贪婪与懒惰
- 剑指Offer面试题51(Java版):数组中重复的数字
- Java并发基础(九)-Fork/Join框架
- 网页websocket正常和C#websocket-csharp 断开连接问题
- android-gson的使用