P2519 [HAOI2011]problem a 題解
阿新 • • 發佈:2021-08-19
Link.
Description.
有 \(n\) 個人,第 \(i\) 個人說有 \(a_i\) 個人成績比他高,有 \(b_i\) 個比他低。
問至少幾個人說謊了。
Solution.
首先考慮每個人說的話本質含義是什麼。
相當於對他來說,第 \(a_i+1\) 個人到第 \(n-b_i\) 人分數相同。
我們分別設 \(l_i=a_i+1,r_i=n-b_i\),那也就是所有所選區間要麼重合要麼互不相連。
然後一個區間最多隻能被重合區間長度次。
那麼直接把重合區間壓縮起來,做一個 dp
即可。
Coding.
點選檢視頹怪程式碼
//是啊,你就是那隻鬼了,所以被你碰到以後,就輪到我變成鬼了{{{ #include<bits/stdc++.h> using namespace std;typedef long long ll; template<typename T>inline void read(T &x) { x=0;char c=getchar(),bz=0; for(;c<48||c>57;c=getchar()) if(!(c^45)) bz=1; for(;c>=48&&c<=57;c=getchar()) x=(x<<1)+(x<<3)+(c^48); bz?x=-x:x; }/*}}}*/ int n,m,F[100005],N; struct node{int l,r,v;}a[100005],b[100005]; inline char cmp1(node x,node y) {return x.l^y.l?x.l<y.l:x.r<y.r;} inline char cmp2(node x,node y) {return x.r^y.r?x.r<y.r:x.l<y.l;} int main() { read(N);for(int i=1;i<=N;i++) read(a[i].l),read(a[i].r),a[i].l++,a[i].r=N-a[i].r; sort(a+1,a+N+1,cmp1);for(int i=1;i<=N;i++) if(a[i].l<=a[i].r) b[++m]=a[i]; for(int i=1;i<=m;i++) if(i==1||b[i].l!=b[i-1].l||b[i].r!=b[i-1].r) a[++n]=b[i],a[n].v=1; else if(a[n].v<a[n].r-a[n].l+1) a[n].v++; sort(a+1,a+n+1,cmp2),F[1]=a[1].v; for(int i=2;i<=n;i++) { int ls=upper_bound(a+1,a+i,(node){0,a[i].l},cmp2)-a-1; F[i]=max(F[i-1],F[ls]+a[i].v); } return printf("%d\n",N-F[n]),0; }