把博客园图标替换成自己的图标
把博客园图标替换成自己的图标end

luogu P2519 [HAOI2011]problem a

题面传送门
这个东西不太好维护,考虑转化成\([a_i+1,n-b_i]\)这一区间中的人分数相同。
则只有选出一些区间,这些区间要么完全重合,要么完全不交,这些人才没有说谎。
显然有\(O(n^2)\)\(dp\)\(dp_i=\min\limits_{j=1}^{i-1}{dp_j+1[(x_i==x_j\&\&y_i==y_j)||x_i>y_j]}\)
这个东西用树状数组随便搞就可以\(O(nlogn)\)了。
代码实现:

#include<cstdio>
#include<algorithm>
#define max(a,b) ((a)>(b)?(a):(b))
using namespace std;
int n,m,k,x,y,z,dp[100039],f[400039],head,now,maxn=1;
struct yyy{int x,y;}s[100039];
inline bool cmp(yyy x,yyy y){return x.x==y.x?x.y<y.y:x.x<y.x;}
inline int find(int x){int ans=0;while(x)ans=max(ans,f[x]),x-=x&-x;;return ans;}
inline void get(int x,int y){while(x<=n) f[x]=max(f[x],y),x+=x&-x;}
int main(){
//	freopen("1.in","r",stdin);
	register int i,j,h;
	scanf("%d",&n);
	for(i=1;i<=n;i++){
		scanf("%d%d",&x,&y);
		if(x+y<n)s[++head].x=x+1,s[head].y=n-y;
	} 
	sort(s+1,s+head+1,cmp);
	for(i=1;i<=head;i++){
		now=0;//printf("%d\n",i);
		for(j=i;j<=head;j++){
			if(s[i].x!=s[j].x||s[i].y!=s[j].y) break;
			now++;
		}
		if(now>s[i].y-s[i].x+1){
			dp[i]=find(s[i].x-1)+1;
			for(h=i+1;h<=i+s[i].y-s[i].x;h++)dp[h]=dp[h-1]+1;
			get(s[h-1].y,dp[h-1]);
		}
		else{
			dp[i]=find(s[i].x-1)+1;
			for(h=i+1;h<j;h++)dp[h]=dp[h-1]+1;
			get(s[h-1].y,dp[h-1]);
		}
		maxn=max(maxn,dp[h-1]);
		i=h-1;
	}
	printf("%d\n",n-maxn);
}
posted @ 2021-01-07 18:43  275307894a  阅读(42)  评论(0编辑  收藏  举报
浏览器标题切换
浏览器标题切换end