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;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章