zoukankan      html  css  js  c++  java
  • P6563-[SBCOI2020]一直在你身旁【dp,单调队列】

    正题

    题目链接:https://www.luogu.com.cn/problem/P6563


    题目大意

    长度为(n)的序列(a_i),现在有一个随机([1,n])的整数,每次你可以花费(a_i)询问这个数字是否大于(i),求猜出所有数至少要多少花费。

    (Tleq 500,sum nleq 7000)

    保证(a_i)单调不降


    解题思路

    考虑区间(dp),设(f_{l,r})表示猜出区间([l,r])的最小花费。

    最基本的转移就是

    [f_{l,r}=min{ max{f_{l,k},f_{k+1,r}}+a_k }( kin[l,r) ) ]

    然后考虑如何优化转移。

    因为里面有个(max),我们可以对于一个(l,r)考虑找到一个最小的(z)满足(f_{l,z}>f_{z+1,r})那么(z)以后的都是用(f_{l,z}),以前的都是用(f_{z+1,r})

    这个在右端点固定左端点向左时(z)是不升的,所以不用二分带(log)

    对于取(f_{l,k}+a_k)的那一部分,(a_k)(f_{l,z})都随着(k)增大不降,所以直接取(f_{l,z}+a_z)

    对于(f_{k+1,r}+a_k)的那一部分,(k)的限制会不断缩小,所以用一个单调队列维护就可以了。

    时间复杂度(O(sum n^2))


    code

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<queue>
    using namespace std;
    const int N=7200;
    int T,n,a[N];
    long long f[N][N];
    deque<int> q;
    long long calc(int k,int r){
    	if(k<1)return 1e18;
    	return f[r][k+1]+a[k];
    }
    signed main()
    {
    	scanf("%d",&T);
    	while(T--){
    		scanf("%d",&n);
    		for(int i=1;i<=n;i++)scanf("%d",&a[i]);
    		for(int i=1;i<=n;i++)
    			for(int j=1;j<=n;j++)
    				if(i!=j)f[i][j]=1e18; 
    		for(int r=2;r<=n;r++){
    			q.clear();q.push_back(r-1);
    			for(int l=r-1,z=r-1;l>=1;l--){
    				while(z>l&&f[z-1][l]>f[r][z])z--;
    				while(!q.empty()&&q.front()>=z)q.pop_front();
    				if(!q.empty())f[r][l]=calc(q.front(),r);
    				f[r][l]=min(f[r][l],f[z][l]+a[z]);
    				if(l==1)continue;
    				while(!q.empty()&&calc(q.back(),r)>=calc(l-1,r))q.pop_back();
    				q.push_back(l-1);
    			}
    		}
    		printf("%lld
    ",f[n][1]);
    	}
    }
    
  • 相关阅读:
    Caffe学习系列(9):solver优化方法
    Caffe学习系列(8):solver,train_val.prototxt,deploy.prototxt及其配置
    模式识别与图像处理笔试题
    图像增强与图像复原
    hough变换检测线和圆
    C++关键字:mutable(转)
    JS 时间格式化函数
    为当前的div 动态添加一个样式
    曾经感动过我们的文字 今天是否还有印象?——v1
    关于模态框 大小的设置 最大 中等 小小
  • 原文地址:https://www.cnblogs.com/QuantAsk/p/15032126.html
Copyright © 2011-2022 走看看