Codeforces 1132 problem C Painting the Fence —— 取n-2个线段的并集最大

2024-04-07 00:32

本文主要是介绍Codeforces 1132 problem C Painting the Fence —— 取n-2个线段的并集最大,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

You have a long fence which consists of n sections. Unfortunately, it is not painted, so you decided to hire q painters to paint it. i-th painter will paint all sections x such that li≤x≤ri.

Unfortunately, you are on a tight budget, so you may hire only q−2 painters. Obviously, only painters you hire will do their work.

You want to maximize the number of painted sections if you choose q−2 painters optimally. A section is considered painted if at least one painter paints it.

Input
The first line contains two integers n and q (3≤n,q≤5000) — the number of sections and the number of painters availible for hire, respectively.

Then q lines follow, each describing one of the painters: i-th line contains two integers li and ri (1≤li≤ri≤n).

Output
Print one integer — maximum number of painted sections if you hire q−2 painters.

Examples
inputCopy
7 5
1 4
4 5
5 6
6 7
3 5
outputCopy
7
inputCopy
4 3
1 1
2 2
3 4
outputCopy
2
inputCopy
4 4
1 1
2 2
2 3
3 4
outputCopy
3

题意:

给你n个线段,让你取其中n-2个,使得他们的并集最大

题解:

真的,不应该看这个标签的。想了好久,交上去以后发现还可以用DP,而且DP代码很短。
我们按左端点为主关键字,右端点为次关键字排序,然后去包含。如果包含的有大于2个,直接输出,如果1个,那么枚举删掉每一个。如果没有覆盖,那么n^2枚举删掉两个的最大值,由于我们是梯度下降的,那么删掉的肯定是只有中间一段了。不会有分开的情况。

#include<bits/stdc++.h>
using namespace std;
const int N=5e3+5;
struct node
{int l,r;bool operator< (const node& a)const{if(l==a.l)return r<a.r;return l<a.l;}
}e[N];
int main()
{int n,m;scanf("%d%d",&n,&m);for(int i=1;i<=m;i++)scanf("%d%d",&e[i].l,&e[i].r);int ans=0;sort(e+1,e+1+m);int sum=0,sta=0,en=0;for(int i=1;i<=m;i++){en=max(en,e[i].r);sta=max(sta,e[i].l);while(sta<=en)sum++,sta++;}int maxn=1e5;int all=0,del=0;for(int i=1;i<=m;i++){if(e[i].l>=e[all].l&&e[i].r<=e[all].r)del++;elsee[++all]=e[i];}if(del>=2)return 0*printf("%d\n",sum);if(del>=1){for(int i=1;i<=all;i++){sta=max(e[i-1].r+1,e[i].l);if(i==all)en=e[i].r;elseen=min(e[i].r,e[i+1].l-1);ans=max(ans,sum-max(0,en-sta+1));}return 0*printf("%d\n",ans);}for(int i=1;i<all;i++){maxn=1e5;sta=max(e[i-1].r+1,e[i].l);en=min(e[i].r,e[i+1].l-1);int cut=max(0,en-sta+1);sta=max(e[i-1].r+1,e[i+1].l);if(i+1==m)en=e[i+1].r;elseen=min(e[i+1].r,e[i+2].l-1);maxn=min(maxn,cut+max(0,en-sta+1));for(int j=i+2;j<=all;j++){sta=max(e[j-1].r+1,e[j].l);if(j==m)en=e[j].r;elseen=min(e[j].r,e[j+1].l-1);maxn=min(maxn,cut+max(0,en-sta+1));}ans=max(ans,sum-maxn);}printf("%d\n",ans);return 0;
}

这篇关于Codeforces 1132 problem C Painting the Fence —— 取n-2个线段的并集最大的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/881233

相关文章

csu 1446 Problem J Modified LCS (扩展欧几里得算法的简单应用)

这是一道扩展欧几里得算法的简单应用题,这题是在湖南多校训练赛中队友ac的一道题,在比赛之后请教了队友,然后自己把它a掉 这也是自己独自做扩展欧几里得算法的题目 题意:把题意转变下就变成了:求d1*x - d2*y = f2 - f1的解,很明显用exgcd来解 下面介绍一下exgcd的一些知识点:求ax + by = c的解 一、首先求ax + by = gcd(a,b)的解 这个

poj3468(线段树成段更新模板题)

题意:包括两个操作:1、将[a.b]上的数字加上v;2、查询区间[a,b]上的和 下面的介绍是下解题思路: 首先介绍  lazy-tag思想:用一个变量记录每一个线段树节点的变化值,当这部分线段的一致性被破坏我们就将这个变化值传递给子区间,大大增加了线段树的效率。 比如现在需要对[a,b]区间值进行加c操作,那么就从根节点[1,n]开始调用update函数进行操作,如果刚好执行到一个子节点,

hdu1394(线段树点更新的应用)

题意:求一个序列经过一定的操作得到的序列的最小逆序数 这题会用到逆序数的一个性质,在0到n-1这些数字组成的乱序排列,将第一个数字A移到最后一位,得到的逆序数为res-a+(n-a-1) 知道上面的知识点后,可以用暴力来解 代码如下: #include<iostream>#include<algorithm>#include<cstring>#include<stack>#in

hdu1689(线段树成段更新)

两种操作:1、set区间[a,b]上数字为v;2、查询[ 1 , n ]上的sum 代码如下: #include<iostream>#include<algorithm>#include<cstring>#include<stack>#include<queue>#include<set>#include<map>#include<stdio.h>#include<stdl

hdu 1754 I Hate It(线段树,单点更新,区间最值)

题意是求一个线段中的最大数。 线段树的模板题,试用了一下交大的模板。效率有点略低。 代码: #include <stdio.h>#include <string.h>#define TREE_SIZE (1 << (20))//const int TREE_SIZE = 200000 + 10;int max(int a, int b){return a > b ? a :

hdu 1166 敌兵布阵(树状数组 or 线段树)

题意是求一个线段的和,在线段上可以进行加减的修改。 树状数组的模板题。 代码: #include <stdio.h>#include <string.h>const int maxn = 50000 + 1;int c[maxn];int n;int lowbit(int x){return x & -x;}void add(int x, int num){while

uva 10025 The ? 1 ? 2 ? ... ? n = k problem(数学)

题意是    ?  1  ?  2  ?  ...  ?  n = k 式子中给k,? 处可以填 + 也可以填 - ,问最小满足条件的n。 e.g k = 12  - 1 + 2 + 3 + 4 + 5 + 6 - 7 = 12 with n = 7。 先给证明,令 S(n) = 1 + 2 + 3 + 4 + 5 + .... + n 暴搜n,搜出当 S(n) >=

poj 3723 kruscal,反边取最大生成树。

题意: 需要征募女兵N人,男兵M人。 每征募一个人需要花费10000美元,但是如果已经招募的人中有一些关系亲密的人,那么可以少花一些钱。 给出若干的男女之间的1~9999之间的亲密关系度,征募某个人的费用是10000 - (已经征募的人中和自己的亲密度的最大值)。 要求通过适当的招募顺序使得征募所有人的费用最小。 解析: 先设想无向图,在征募某个人a时,如果使用了a和b之间的关系

poj 3258 二分最小值最大

题意: 有一些石头排成一条线,第一个和最后一个不能去掉。 其余的共可以去掉m块,要使去掉后石头间距的最小值最大。 解析: 二分石头,最小值最大。 代码: #include <iostream>#include <cstdio>#include <cstdlib>#include <algorithm>#include <cstring>#include <c

poj 1127 线段相交的判定

题意: 有n根木棍,每根的端点坐标分别是 px, py, qx, qy。 判断每对木棍是否相连,当他们之间有公共点时,就认为他们相连。 并且通过相连的木棍相连的木棍也是相连的。 解析: 线段相交的判定。 首先,模板中的线段相交是不判端点的,所以要加一个端点在直线上的判定; 然后,端点在直线上的判定这个函数是不判定两个端点是同一个端点的情况的,所以要加是否端点相等的判断。 最后