Written with StackEdit.

Description

一次考试共有\(n\)个人参加,第\(i\)个人说:“有\(a_i\)个人分数比我高,\(b_i\)个人分数比我低。”问最少有几个人没有说真话(可能有相同的分数).

Input

第一行一个整数\(n\),接下来\(n\)行每行两个整数,第\(i+1\)行的两个整数分别代表\(a_i,b_i.\)

Output

一个整数,表示最少有几个人说谎.

Sample Input

3

2 0

0 2

2 2

Sample Output

1

HINT

\(100\%\)的数据满足: \(1≤n≤100000 0≤a_i,b_i≤n.\)

Solution

  • 一句话题面系列...
  • 关键在于条件的转化.有\(a\)个人严格比他大,\(b\)个人严格比他小,
  • 若将分数从大到小排序,如果这句话为真,那么易知:
  • 性质1这个人的分数一定属于\([a+1,n-b]\),且这个区间内所有人的分数都相同.
  • 性质2这个区间外的分数都与区间内的分数不同.
  • 首先可以排除掉区间左端点大于右端点的人,这些话一定为假.
  • 对于剩下的人,我们假设这些话都为真,可以得到若干个区间.
  • 如果两个区间相交,而又不完全重合,将这两个区间并起来显然可以得到更大的分数相同区间,不符合性质2.而对于完全相同的两个区间,而根据性质1,针对这个区间的话,最多可以有\(r-l+1\)(区间长度)句话为真.
  • 那么可以给每个区间赋一个权值,为这个区间的重复次数与区间长度的最小值.我们现在选出若干个不相交的区间,这些区间的最大权值和即为最多说真话的人数.
  • 这里就是一个\(dp\)了.优化方法多样,我选择无需思考的树状数组.
#include<bits/stdc++.h>
using namespace std;
typedef long long LoveLive;
inline int read()
{
	int out=0,fh=1;
	char jp=getchar();
	while ((jp>'9'||jp<'0')&&jp!='-')
		jp=getchar();
	if (jp=='-')
		{
			fh=-1;
			jp=getchar();
		}
	while (jp>='0'&&jp<='9')
		{
			out=out*10+jp-'0';
			jp=getchar();
		}
	return out*fh;
}
const int MAXN=1e5+10;
int n,tot,unitot;
struct sec{
	int l,r;
	int w;
	bool operator < (const sec& rhs) const
		{
			return r==rhs.r?l<rhs.l:r<rhs.r;
		}
}s[MAXN],p[MAXN];
#define lowbit(x) x&(-x)
int bit[MAXN];
inline void upd(int x,int c)
{
	for(;x<=n;x+=lowbit(x))
		bit[x]=max(bit[x],c);	
}
inline int query(int x)
{
	if(x<=0)
		return 0;
	int res=0;
	for(;x;x-=lowbit(x))
		res=max(res,bit[x]);
	return res;
}
void UniqueSec()
{
	for(int i=1;i<=tot;++i)
		{
			if(i==1 || s[i].l!=s[i-1].l || s[i].r!=s[i-1].r)
				++unitot;
			p[unitot].w=min(p[unitot].w+1,p[unitot].r-p[unitot].l+1);
			p[unitot].l=s[i].l;
			p[unitot].r=s[i].r;
		}
}
int main()
{
	n=read();
	for(int i=1;i<=n;++i)
		{
			int a=read(),b=read();
			int l=a+1;
			int r=n-b;
			if(l<=r)
				{
					s[++tot].l=l;
					s[tot].r=r;
				}
		}
	sort(s+1,s+1+tot);
	UniqueSec();
	for(int i=1;i<=unitot;++i)
		{
			int l=p[i].l,r=p[i].r;
			int val=query(l-1)+p[i].w;
			upd(r,val);
		}
	int ans=n-query(n);
	printf("%d\n",ans);
	return 0;
}

相关文章:

  • 2021-07-17
  • 2022-02-01
  • 2022-01-24
  • 2021-07-12
  • 2022-03-08
  • 2022-12-23
  • 2022-12-23
  • 2021-09-26
猜你喜欢
  • 2021-07-27
  • 2021-05-27
  • 2021-10-20
  • 2021-07-22
  • 2022-12-23
  • 2022-03-04
  • 2022-03-05
相关资源
相似解决方案