zoukankan      html  css  js  c++  java
  • 跳房子

    这道题是一道普及组的题 但是好像也没有那么简单
    首先这道题用到的东西有:二分答案,单调队列优化dp
    我们将最后的答案二分 然后用单调队列优化dp进行检验
    因为我们发现 对于(f_i)来说 他的更新一定是从前面他能取到区间的最大值进行更新 这就符合了单调队列的性质,考虑用单调队列维护一个单减序列
    代码如下:

    #include <cstdio>
    #include <iostream>
    #include <cstring>
    #include <algorithm>
    #define int long long 
    using namespace std;
    const int maxn=500010;
    struct node{
    	int pos,val;
    };
    node a[maxn],q[maxn];
    int ans[maxn],n,d,k;
    const int inf=1e9;
    signed main()
    {
    	scanf("%lld %lld %lld",&n,&d,&k);
    	for(int i=1;i<=n;i++)
    		scanf("%lld %lld",&a[i].pos,&a[i].val);
    	a[0].pos=a[0].val=0;
    	int l=0,r=1e9+1;
    	while(l<r)
    	{
    		int mid=l+r>>1;
    		int head=1,tail=0;
    		int now=0,lower,upper;
    		lower=d-mid;upper=d+mid;
    		lower=max(lower,(long long)1);
    		bool flag=false;
    		for(int i=1;i<=n;i++)
    		{
    			while(a[now].pos<=a[i].pos-lower){
    				while(head<=tail && q[tail].val<=ans[now])
    					tail--;
    				tail++;
    				q[tail].pos=a[now].pos;
    				q[tail].val=ans[now];
    				now++;
    			}
    			while(head<=tail && q[head].pos+upper<a[i].pos)
    				head++;
    			if(head>tail)
    				ans[i]=-10000000000000000LL;
    			else 
    				ans[i]=q[head].val+a[i].val;
    			if(ans[i]>=k)
    			{
    				flag=true;
    				break;
    			}
    		}
    		if(flag)	r=mid;
    		else l=mid+1;
    	}
    	l=(l<=1e9)?l:-1;
    	printf("%lld",l);
    	return 0;
    }
  • 相关阅读:
    【BZOJ 1455】罗马游戏
    【UR #2】树上GCD
    1067: [SCOI2007]降雨量
    1068: [SCOI2007]压缩
    1066: [SCOI2007]蜥蜴
    1065: [NOI2008]奥运物流
    1064: [Noi2008]假面舞会
    1063: [Noi2008]道路设计
    2329: [HNOI2011]括号修复
    2734: [HNOI2012]集合选数
  • 原文地址:https://www.cnblogs.com/mendessy/p/11729188.html
Copyright © 2011-2022 走看看