• CF1257E The Contest


    洛谷题目链接

    题目分析

    只要保证(a_1)(a_3)满足条件即可,所以我们几乎可以忽略(a_2).

    为了方便下面讲解,简化一下题面.

    将每个元素想象成一棵棵带有编号的树,要通过一系列的操作,

    将树种在上方((a_1)处),或种在下方((a_3)处),或因生长发育不合格而被扔掉((a_2)处),然后求最少次数使满足题目要求.

    (读者看到此处可根据简化题面再独立思考一下如何解题)

    思路解析

    最优答案一类的问题,想到DP.

    (F_{i,0/1/2})表示所有树里到第i课时扔掉/种在上方/种在下方    的最少操作次数,接下来要分情况讨论(第i棵树的原始状态):

    1.在上方

    (F_{i,0}=min(F_{i-1,1},F_{i-1,0})+ 1)  如果这棵树被扔掉,那前面一棵一定不是种在下面

    (F_{i,1}=F_{i-1,1})  这棵树不动,对答案没贡献

    (F_{i,2}=min) { (F_{i-1,2},F_{i-1}{1},F_{i-1,0})} (+1)  如果这棵树被种在下面,则前面树的状态无所谓

    2.在下方

    (F_{i,0}=min(F_{i-1,1},F_{i-1,0})+ 1)

    (F_{i,1}=F_{i-1,1} + 1)

    (F_{i,2}=min) { (F_{i-1,2},F_{i-1}{1},F_{i-1,0})}

    理解同第一种情况,但要注意是否+1的问题

    3.在(a_2)垃圾箱

    方程思路与1,2种情况相同,请读者自行推理

    4.端点

    第一棵树比较特殊,无法从第0棵树转移过来,需要初始化处理一下.

    另外说一下时间复杂度,状态转移方程的复杂度是(O(n))但是所有的树需要按照编号从小到大排序,所以时间复杂度为(O(nlogn))

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    
    using namespace std;
    
    int n,m,t,a[200001],b[200001],c[200001],f[200001][3],d[200001],mx,oo;
    
    inline int pd(int x,int y) {
    	if(b[x] >= c[y]) return y;
    	return x;
    }
    
    inline bool cmp(int x,int y) {
    	return x < y;
    }
    
    int main() {
    	scanf("%d%d%d",&n,&m,&t);
    	for(int i = 1;i <= n; i++) {
    		int u;
    		scanf("%d",&u);
    		d[++mx] = u;
    		a[u] = 1;
    		++oo;
    	}
    	for(int i = 1;i <= m; i++) {//因为a2可以被忽略,所以不做任何处理 
    		int x;
    		scanf("%d",&x);
    	}
    	for(int j = 1;j <= t; j++)  {
    		int x;
    		scanf("%d",&x);
    		d[++mx] = x;
    		a[x] = 2;
    	}
    	n = n + m + t;
    	sort(d+1,d+mx+1,cmp);
    	if(a[1] == 1) f[1][0] = f[1][2] = 1;
    	if(a[1] == 0) f[1][1] = f[1][2] = 1;
    	if(a[1] == 2) f[1][1] = f[1][0] = 1;
    	for(int i = 2;i <= n; i++) {
    		if(a[i] == 0) {
    			f[i][0] = min(f[i-1][1],f[i-1][0]);
    			f[i][1] = f[i-1][1] + 1;
    			f[i][2] = min(f[i-1][2],min(f[i-1][0],f[i-1][1])) + 1;
    		}
    		if(a[i] == 2) {
    			f[i][0] = min(f[i-1][1],f[i-1][0]) + 1;
    			f[i][1] = f[i-1][1] + 1;
    			f[i][2] = min(f[i-1][2],min(f[i-1][1],f[i-1][0]));
    		}
    		if(a[i] == 1) {
    			f[i][0] = min(f[i-1][1],f[i-1][0]) + 1;
    			f[i][1] = f[i-1][1];
    			f[i][2] = min(f[i-1][2],min(f[i-1][1],f[i-1][0])) + 1;
    		}
    	}
    	printf("%d",min(f[n][1],min(f[n][0],f[n][2])));
    	return 0;
    }
    
  • 相关阅读:
    iOS地图开发
    常用iOS第三方库以及XCode插件介绍
    SDWebImage内部实现过程
    iOS-线程之GCD---之GCD的几种常用常用的方法
    iOS-线程之GCD方式---之同步异步和串行队列并行队列之间的关系
    iOS-获取系统的相册图片
    iOS开发-使用第三方库AFNetWorking解析JSON和XML数据
    iOS_UITableView上拉加载,下拉刷新
    launchImage
    launchImage
  • 原文地址:https://www.cnblogs.com/lipeiyi520/p/14431037.html
Copyright © 2020-2023  润新知