题目描述
一次考试共有n个人参加,第i个人说:“有ai个人分数比我高,bi个人分数比我低。”问最少有几个人没有说真话(可能有相同的分数)
输入输出格式
输入格式:第一行一个整数n,接下来n行每行两个整数,第i+1行的两个整数分别代表ai、bi
输出格式:一个整数,表示最少有几个人说谎
输入输出样例
说明
100%的数据满足: 1≤n≤100000 0≤ai、bi≤n
题目的本质并不难,难点在于对题提转化上:
比如有一行告诉你,有a个比他大,有b个比他小,那也就是说,前a个比他的并且大小关系不缺定,后b个比他小并且大小关系不确定,他是从a+1到n-y这段区间的数字全相等,这是题目也就转化为了 给你m个区间,每个区间的价值为v,让你选不相交的区间使得得到的价值最大,
要点:同一个区间可能有多个,使用了map计数。同一个区间的个数不能超过区间的长度。
1 #include"bits/stdc++.h"
2 #define lson rt<<1,l,mid
3 #define rson rt<<1|1,mid+1,r
4
5 using namespace std;
6
7 map<pair<int ,int >,int > mp;
8
9 int tr[4000000];
10 struct aa
11 {
12 int l,r;
13 bool operator<(const aa b)const
14 {
15 return r==b.r?l<b.l:r<b.r;
16 }
17 }a[200000]; int tot;
18
19 namespace segtree
20 {
21 int que(int rt,int l,int r,int L,int R)
22 {
23 if(L>R)return 0;
24 // cout<<l<<" "<<r<<endl;
25 if(L<=l&&r<=R)return tr[rt]; int mid=l+r>>1;
26 int res=-1; if(L<=mid)res=max(res,que(rt<<1,l,mid,L,R));
27 if(R>mid)res=max(res,que(rt<<1|1,mid+1,r,L,R));
28 return res;
29 }
30 void upd(int rt,int l,int r,int pos,int v)
31 {
32 if(l==r){tr[rt]=max(tr[rt],v);return ;} int mid=l+r>>1;
33 if(pos<=mid)upd(lson,pos,v);else upd(rson,pos,v);
34 tr[rt]=max(tr[rt<<1],tr[rt<<1|1]);
35 }
36
37
38 }using namespace segtree;
39
40 int dp[200000];
41
42 int main()
43 {
44 int n; cin>>n;
45 for (int i=1;i<=n;i++)
46 {
47 int x,y;scanf("%d%d",&y,&x);if(x+y+1>n)continue;
48 if(!mp[make_pair(x+1,n-y)])
49 {
50 a[++tot].l=x+1,a[tot].r=n-y,mp[make_pair(x+1,n-y)]++;
51 }
52 else if(mp[make_pair(x+1,n-y)]<n-y-x-1+1)
53 mp[make_pair(x+1,n-y)]++;
54
55 }
56 sort(a+1,a+1+tot);
57
58 for (int i=1;i<=tot;i++)
59 {
60 dp[a[i].r]=max(dp[a[i].r],que(1,0,n,0,a[i].l-1)+mp[make_pair(a[i].l,a[i].r)]);//cout<<i<<endl;
61 upd(1,0,n,a[i].r,dp[a[i].r]);
62 }
63 int ans=0;
64 for(int i=1;i<=n;i++)ans=max(ans,dp[i]);
65 cout<<n-ans;
66
67
68
69
70
71 }