BZOJ 2298: [HAOI2011]problem a
阿新 • • 發佈:2017-10-23
mes sca ret des shu insert define page bsp
Submit: 1523 Solved: 756
[Submit][Status][Discuss]
3
2 0
0 2
2 2
1
2298: [HAOI2011]problem a
Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 1523 Solved: 756
[Submit][Status][Discuss]
Description
一次考試共有n個人參加,第i個人說:“有ai個人分數比我高,bi個人分數比我低。”問最少有幾個人沒有說真話(可能有相同的分數)
Input
第一行一個整數n,接下來n行每行兩個整數,第i+1行的兩個整數分別代表ai、bi
Output
一個整數,表示最少有幾個人說謊
Sample Input
2 0
0 2
2 2
Sample Output
1
HINT
100%的數據滿足: 1≤n≤100000 0≤ai、bi≤n
題解:
這個題目還是比較巧妙的。
首先分析題意,一個人說出的其實是一個區間,表示ai+1~n-bi必須相等,並且其他位置都和這個區間的元素不相等,那麽對於兩個相交的區間,他們一定有一個是不合法的,對於相等的區間,假如說區間長度為len,那麽區間個數超過len的顯然超過的部分也是不和法,同理,相互包含的也是不合法的,所以每個區間,我們統計和他相等的區間個數作為權值,這樣就轉化為選擇若幹權值不想交的區間使得權值最大化。
分析到這,就是一個簡單dp了,主要還是轉化有一定的難度。
代碼:
#include <cstdio> #include <iostream> #include <algorithm> #include <cstring> #include <cmath> #include <iostream> #define MAXN 100010 using namespace std; struct node{ int l,r,maxx; }a[MAXN*4]; struct qvjian{int l,r,v; }qv[MAXN]; bool cmp(qvjian x,qvjian y){ if(x.l==y.l) return x.r<y.r; else return x.l<y.l; } void pushup(int xv){ a[xv].maxx=max(a[xv*2].maxx,a[xv*2+1].maxx); } void build(int xv,int l,int r){ if(l==r){ a[xv].l=l,a[xv].r=r; a[xv].maxx=0; return; } a[xv].l=l,a[xv].r=r; int mid=(l+r)/2; build(xv*2,l,mid),build(xv*2+1,mid+1,r); pushup(xv); } int n,num=0; int query(int xv,int l,int r){ int L=a[xv].l,R=a[xv].r,mid=(L+R)/2; if(l==L&&r==R){ return a[xv].maxx; } if(r<=mid) return query(xv*2,l,r); else if(l>mid) return query(xv*2+1,l,r); else return max(query(xv*2,l,mid),query(xv*2+1,mid+1,r)); } void insert(int xv,int ps,int x){ int l=a[xv].l,r=a[xv].r,mid=(l+r)/2; if(l==r){ a[xv].maxx=max(a[xv].maxx,x); return; } if(ps<=mid) insert(xv*2,ps,x); else insert(xv*2+1,ps,x); pushup(xv); } int main() { scanf("%d",&n); for(int i=1;i<=n;i++){ int l,r;scanf("%d%d",&l,&r); l=l+1,r=n-r; if(l<=r) {qv[++num].l=l;qv[num].r=r,qv[num].v=1;} } sort(qv+1,qv+num+1,cmp); int ps=0; for(int i=1;i<=num;i++){ if(qv[ps].l==qv[i].l&&qv[ps].r==qv[i].r) qv[ps].v++; else qv[++ps]=qv[i]; } for(int i=1;i<=ps;i++){ int len=qv[i].r-qv[i].l+1; if(qv[i].v>len) qv[i].v=len; } build(1,1,n); int ans=0; for(int i=1;i<=n;i++){ int now; if(qv[i].l-1>0) now=qv[i].v+query(1,1,qv[i].l-1); else now=qv[i].v; ans=max(ans,now); insert(1,qv[i].r,now); } printf("%d\n",n-ans); return 0; }
BZOJ 2298: [HAOI2011]problem a