【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; 
}
  

 

posted @ 2018-09-02 22:41  尹吴潇  阅读(183)  评论(0编辑  收藏  举报