【BZOJ2298】[HAOI2011]problem a
题解:
虽然也是个可以过得做法。。。但又没有挖掘到最简单的做法。。。
正解是发现这个东西等价于求不相交区间个数
直接按照右端点排序,然后贪心就可以O(n)过了
而我的做法是按照a排序(其实我是在模拟这个过程但我没有发现他的本质。。。)
然后f[i][j]表示前i个,最大要求为j的最大值
然后用线段树来优化这个东西
一个地方存在的东西还要取个min
代码:
#include <bits/stdc++.h> using namespace std; #define rint register int #define IL inline #define rep(i,h,t) for (rint i=h;i<=t;i++) #define dep(i,t,h) for (rint i=t;i>=h;i--) #define mid ((h+t)/2) const int N=2e5+100; struct re{ int a,b,c; }a[N],b[N]; bool cmp(re x,re y) { return (x.a<y.a||(x.a==y.a&&x.b<y.b)); } struct sgt{ int v[N*4]; int find(int x,int h,int t,int h1,int t1) { if (t1<h1) return(0); if (h1<=h&&t<=t1) return(v[x]); int ans=0; if (h1<=mid) ans=find(x*2,h,mid,h1,t1); if (mid<t1) ans=max(ans,find(x*2+1,mid+1,t,h1,t1)); return(ans); } void change(int x,int h,int t,int pos,int k) { if (h==t) { v[x]=max(v[x],k); return; } if (pos<=mid) change(x*2,h,mid,pos,k); else change(x*2+1,mid+1,t,pos,k); v[x]=max(v[x*2],v[x*2+1]); } }S; int main() { freopen("1.in","r",stdin); freopen("1.out","w",stdout); ios::sync_with_stdio(false); int n; cin>>n; rep(i,1,n) cin>>a[i].a>>a[i].b; sort(a+1,a+n+1,cmp); int l=0; rep(i,1,n) if (a[i].a==a[i-1].a&&a[i].b==a[i-1].b) b[l].c++,b[l].c=min(b[l].c,n-a[i].a-a[i].b); else { b[++l].a=a[i].a; b[l].b=a[i].b; b[l].c=1; } rep(i,1,l) { int x=S.find(1,1,n,1,b[i].a); S.change(1,1,n,n-b[i].b,x+b[i].c); } int ans=S.find(1,1,n,1,n); cout<<n-ans<<endl; return 0; }