LYDSY模拟赛day2 Market

/*
orz claris,这个题的解法非常巧妙,首先是时间问题,其实这个问题只要离线处理一下就可以了,把物品和询问都按照时间排序,然后看一下能不能满足。然后,因为容量<=10^9,显然是不可能开一个这么大的数组,而且这么大一个容量,价值又很小,我们可以考虑用二分解决
对每个询问二分答案,需要判定用容量为 M 的背包是否可
以装下 mid 的价值。
设 fi 表示装了 i 价值所需的最小容量,gi 表示
min(fi,fi+1,fi+2,……)。
那么只需要检查 gmid 是否不超过 M 即可。
时间复杂度 O(n2v + m log m)。
*/
#include<cstdio>
#include<algorithm>
using namespace std;
const int N=305,M=100010,inf=1000000010;
int n,m,lim,i,j,f[M],ans[M];
struct P{int t,c,v;}a[N];
struct Q{int t,m,p;}b[M];
bool cmpP(const P&a,const P&b){return a.t<b.t;}
bool cmpQ(const Q&a,const Q&b){return a.t<b.t;}
void add(int c,int v){
  for(int i=lim;i>=v;i--)f[i]=min(f[i],f[i-v]+c);
  for(int i=lim-1;~i;i--)f[i]=min(f[i],f[i+1]);
}
int ask(int x){
  int l=0,r=lim,mid,t;
  while(l<=r)if(f[mid=(l+r)>>1]<=x)l=(t=mid)+1;else r=mid-1;
  return t;
}
int main(){
  freopen("market.in","r",stdin);freopen("market.out","w",stdout);
  scanf("%d%d",&n,&m);lim=n*300;
  for(i=1;i<=n;i++)scanf("%d%d%d",&a[i].c,&a[i].v,&a[i].t);
  for(i=1;i<=m;i++)scanf("%d%d",&b[i].t,&b[i].m),b[i].p=i;
  sort(a+1,a+n+1,cmpP);
  sort(b+1,b+m+1,cmpQ);
  for(i=1;i<=lim;i++)f[i]=inf;
  for(i=j=1;i<=m;i++){
    while(j<=n&&a[j].t<=b[i].t)add(a[j].c,a[j].v),j++;
    ans[b[i].p]=ask(b[i].m);
  }
  for(i=1;i<=m;i++)printf("%d\n",ans[i]);
  fclose(stdin);fclose(stdout);
  return 0;
}
时间: 2024-06-13 11:47:58

LYDSY模拟赛day2 Market的相关文章

LYDSY模拟赛day2 Dash Speed

/* 弃坑 */ #include<cstdio> #include<algorithm> using namespace std; const int N=70010,M=N*20; int n,m,i,g[N],v[N<<1],nxt[N<<1],ed,cur,ans[N]; int size[N],f[N],d[N],son[N],top[N]; int fa[N],dep[N],A[N],B[N]; int G[262150],V[M],W[M],N

LYDSY模拟赛day2 Divisors

/* 注意分解质因数,如果i是,那么n/i也是,这样就可以解决分解质因数的时间问题了 当 k ≥ 1 时,只有这些数的约数才会对答案产生贡献. 求出 m 个数的所有不超过 n 的约数,去重后统计即可. 求出 k = 1 到 m 的所有答案后,剩下的数字个数就是 k = 0 的答案. 时间复杂度 O(m2√a) */ #include<cstdio> #include<algorithm> const int N=205; int n,m,i,a[N],cnt,b[1000000],

CH Round #55 - Streaming #6 (NOIP模拟赛day2)解题报告

T1九九归一 描述 萌蛋在练习模n意义下的乘法时发现,总有一些数,在自乘若干次以后,会变成1.例如n=7,那么5×5 mod 7=4,4×5 mod 7=6,6×5 mod 7=2,2×5 mod 7=3,3×5 mod 7=1.如果继续乘下去,就会陷入循环当中.萌蛋还发现,这个循环的长度经常会是φ(n),即小于n且与n互质的正整数的个数.例如,φ(7)=6,而上述循环的长度也是6,因为5,4,6,2,3,1共有6个数.再如n=6,那么5×5 mod 6=1.这个循环的长度很短,只有2,而恰好φ

2016.10.30 NOIP模拟赛 day2 PM 整理

满分:300分 直接全部爆零,真的是很坑啊! 10.30的题目+数据:链接:http://pan.baidu.com/s/1jHXLace 密码:i784 T1: 题目中的难点就是每次折叠的点可能应经被覆盖了,我的做法是递归去推出它现在在哪个位置,不仅超时,而且答案错误. 也曾想过用数组去存下它当前的位置,但是被10^18的数据吓到了. 正解:并不是所有的坐标都有用,仅仅是那m个将要用到的点有用,所以每次折叠,就只对之后的有用的k个点进行更新,这样就行了. 时间复杂度O(m^2) 不会超时的.

LYDSY模拟赛day3 序列

NOIP不考可持久,弃坑

LYDSY模拟赛day1 Walk

/* 依旧考虑新增 2^20 个点. i 只需要向 i 去掉某一位的 1 的点连边. 这样一来图的边数就被压缩到了 20 · 2^20 + 2n + m,然后 BFS 求出 1 到每个点的最短路即可. 时间复杂度 O(20 · 2^20 + n + m) */ #include<cstdio> const int N=1300000,M=700010; int n,m,i,x,y,cnt,g0[N],g1[N],v[M],nxt[M],ed,h,t,q[N],d[N]; void add(in

NOI模拟赛Day2

深深的感受到了自己的水 -------------------------------------------------------------------------------------------------------------------------- T1: 题意:一棵树,有k个关键点,求分成连通块,每块至少一个关键点,使连通块最大最小. woc我为啥没想到二分,不懂啊,考试的时候是在梦游吗 二分后判断是否可行 就是一个简单的树上的贪心 可以先bfs一遍倒着来,max表示改点最

2016.10.30 NOIP模拟赛 day2 AM 整理

题目+数据:链接:http://pan.baidu.com/s/1gfBg4h1 密码:ho7o 总共得了:130分, 1:100分  2:30分(只会这30分的暴力) 3:0(毫无思路) 虽然不高,但是比较满意,因为把自己会的分数都拿到了. T1:100分 1 /* 2 T1明显是个数论题. 3 正确的思路:把n!质因数分解,把所有质因数的指数都取到最大的偶数,它们的乘积便是最终的结果. 4 有一种很快的方法在Eular筛中可以n!的质因数分解. 5 if(!is_prim[i]) 6 { 7

LYDSY模拟赛 escape

Description 给出数字N(1<=N<=10000),X(1<=x<=1000),Y(1<=Y<=1000),代表有N个敌人分布一个X行Y列的矩阵上矩形的行号从0到X-1,列号从0到Y-1再给出四个数字x1,y1,x2,y2,代表你要从点(x1,y1)移到(x2,y2).在移动的过程中你当然希望离敌人的距离的最小值最大化,现在请求出这个值最大可以为多少,以及在这个前提下你最少要走多少步才可以回到目标点.注意这里距离的定义为两点的曼哈顿距离,即某两个点的坐标分为(