ICPC Pacific Northwest Regional Contest 2016 - Paint(线段树+dp)

You are painting a fence with n sections, numbered from 1 to n. There are k artists, each willingto paint their design on a specific portion of the fence. However, artists will never agree to havetheir section painted over, so they will only paint their portion of the fence if no one else will paintany part of it. 

You want to select a set of painters that does not conflict to minimize the number of unpaintedsections.

Input

The first line contains two positive integers n (1 ≤ n ≤ 10^18) and k (1 ≤ k ≤ 200,000).

Each of the next k lines contains two positive integers ai and bi, where 1 ≤ ai ≤ bi ≤ n, indicatingthat the ith artist wants to paint all sections between section ai and section bi, inclusive.

Output

Print, on a single line, a single integer indicating the minimum number of unpainted sections.

样例输入复制

8 3
1 3
2 6
5 8

样例输出复制

1

题目链接:点击查看

题目大意:给出 m 个闭区间,现在要求选出任意个没有交集的闭区间,使得总的覆盖点数最多,n - ans 是这个题目的答案

题目分析:之前网络流做过类似的题目,但是数据太大了,这个题目只能考虑 dp,首先对所有断点离散化,然后对所有的区间以左端点升序排序,dp[ i ] 代表以第 i 段区间为结尾的最大长度,转移方程为 dp[ i ] = max( dp[ i ] , mmax + r - l + 1 ) ,其中 mmax 是前面 i - 1 个 dp 中,区间结尾小于等于 l - 1 的位置的最大值,区间最大值可以用线段树来维护,这个dp可以理解为 n * n 的最长不下将子序列的状态以及转移,转移的过程中维护一下最大值就是答案了

代码:
 

#include<iostream>
#include<cstdio>
#include<string>
#include<ctime>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<stack>
#include<climits>
#include<queue>
#include<map>
#include<set>
#include<sstream>
#include<cassert>
#include<unordered_map>
using namespace std;

typedef long long LL;

typedef unsigned long long ull;

const int inf=0x3f3f3f3f;

const int N=1e6+100;

vector<LL>node;

LL dp[N];

void discreate()
{
	sort(node.begin(),node.end());
	node.erase(unique(node.begin(),node.end()),node.end());
}

int get_id(LL x)
{
	return lower_bound(node.begin(),node.end(),x)-node.begin()+1;
}

struct Seg
{
	LL l,r;
	bool operator<(const Seg& t)const
	{
		if(l!=t.l)
			return l<t.l;
		return r<t.r;
	}
}a[N];

struct Node
{
	int l,r;
	LL mmax;
}tree[N<<2];

void pushup(int k)
{
	tree[k].mmax=max(tree[k<<1].mmax,tree[k<<1|1].mmax);
}

void build(int k,int l,int r)
{
	tree[k].l=l;
	tree[k].r=r;
	tree[k].mmax=0;
	if(l==r)
		return;
	int mid=l+r>>1;
	build(k<<1,l,mid);
	build(k<<1|1,mid+1,r);
}

void update(int k,int pos,LL val)
{
	if(tree[k].l==tree[k].r)
	{
		tree[k].mmax=max(val,tree[k].mmax);
		return;
	}
	int mid=tree[k].l+tree[k].r>>1;
	if(pos<=mid)
		update(k<<1,pos,val);
	else
		update(k<<1|1,pos,val);
	pushup(k);
}

LL query(int k,int l,int r)
{
	if(l>r)
		return 0;
	if(tree[k].r<l||tree[k].l>r)
		return 0;
	if(tree[k].l>=l&&tree[k].r<=r)
		return tree[k].mmax;
	return max(query(k<<1,l,r),query(k<<1|1,l,r));
}

int main()
{
#ifndef ONLINE_JUDGE
//  freopen("input.txt","r",stdin);
//  freopen("output.txt","w",stdout);
#endif
//  ios::sync_with_stdio(false);
	LL n,m;
	scanf("%lld%lld",&n,&m);
	for(int i=1;i<=m;i++)
	{
		scanf("%lld%lld",&a[i].l,&a[i].r);
		node.push_back(a[i].l-1);
		node.push_back(a[i].l);
		node.push_back(a[i].r);
	}
	discreate();
	build(1,1,node.size());
	sort(a+1,a+1+m);
	LL ans=0;
	for(int i=1;i<=m;i++)
	{
		LL l=a[i].l,r=a[i].r;
		LL mmax=query(1,1,get_id(a[i].l-1));
		dp[i]=mmax+r-l+1;
		update(1,get_id(a[i].r),dp[i]);
		ans=max(ans,dp[i]);
	}
	printf("%lld\n",n-ans);










    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_45458915/article/details/106890678