BZOJ2298: [HAOI2011]problem a

Description

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

Input

第一行一个整数n,接下来n行每行两个整数,第i+1行的两个整数分别代表ai、bi

Output

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

Sample Input

3

2 0

0 2

2 2

Sample Output

1

HINT

100%的数据满足: 1≤n≤100000   0≤ai、bi≤n

太久没更博了证明一下自己还活着

考虑转化下题目,对于每一人说的话,可以把他转化成一条线段

然后就变成了每段线段都有一个权值,找一些线段互不相交且权值和最大

那就DP套一个树状数组即可

有个小细节:每段线段权值最大只能是它的长度

//MT_LI
#include<cmath> #include<cstdio> #include<cstring> #include<cstdlib> #include<algorithm> using namespace std; int n,N; struct segment{ int x,y,c; }a[110000]; int cc[110000]; int lowbit(int x){return x&-x;} void change(int x,int d){while(x<=N){cc[x]=max(cc[x],d),x+=lowbit(x);}} int getsum(int x){int ans=0;while(x){ans=max(ans,cc[x]);x-=lowbit(x);}return ans;} bool cmp(segment a,segment b){return a.x!=b.x?a.x<b.x:a.y<b.y;} int main() { scanf("%d",&n);N=n; for(int i=1;i<=n;i++) { int x,y; scanf("%d%d",&x,&y); a[i].x=y+1,a[i].y=n-x;a[i].c=1; if(a[i].x>a[i].y)a[i].x=1<<30; } sort(a+1,a+n+1,cmp); int pos=1; for(int i=2;i<=n;i++) { if(a[i].x!=a[pos].x||a[pos].y!=a[i].y){pos=i;continue;} else { a[i].x=a[i].y=1<<30; a[pos].c++;if(a[pos].c>a[pos].y-a[pos].x+1)a[pos].c=a[pos].y-a[pos].x+1; } } sort(a+1,a+1+n,cmp); for(int i=1;i<=n;i++)if(a[i].x==1<<30){n=i-1;break;} change(a[1].y,a[1].c); for(int i=2;i<=n;i++) change(a[i].y,a[i].x==1?0:getsum(a[i].x-1)+a[i].c); printf("%d ",N-getsum(N)); return 0; }
原文地址:https://www.cnblogs.com/MT-LI/p/9814713.html