codeforces 264E Roadside Trees

来源:互联网 发布:淘宝上买iphone4s 编辑:程序博客网 时间:2024/05/16 06:37

/*

看完题目:靠,这什么玩意儿?能做?

看完数据范围:靠,似乎还可作!

*/


注意到hi<=10,xi<=10,保证任何时刻高度两两不同,于是我们踏上了暴力之路。。。。


我们需要维护的是数组的最长上升序列。

dp[i]表示开头为i的最长上升序列

操作1      对于新增的i,一定是在其后的高度大于hi的树才能转移,而受到i影响的一定是i之前的高度小于hi的。维护一个线段树,以x为下标,dp为权值,支持区间求最大值。我们将高度大于10的全部树的dp全部放进去,小于10的由于总数不会超过10个,直接暴力即可。

操作2      找到第x个树之后(我用的是树状数组),乱搞啦!在维护一颗线段树,以高度为下标,dp为权值,维护除前10棵树的最大值。利用者棵线段树+暴力重新计算前10棵树的dp

/*不要问我复杂度,我自己也不会算了。。。。*/


#include <list>#include <cstdio>#include <cstring>#include <algorithm>using namespace std;#define lowbit(x) ((x)&(-(x)))int maxx[400005],dp[100005],tr[100005];int maxx2[800020],ht[100005];int n,m,M,tim,ans,x,y,xx,typ,i,j;list <int> c;list <int>::iterator I,J;void add(int p,int l,int r,int x){  if (l==r && l==x) {maxx[p]=dp[x]; return;}  int mid=(l+r)>>1;  if (x<=mid) add(p*2+1,l,mid,x);    else add(p*2+2,mid+1,r,x);  maxx[p]=max(maxx[p*2+1],maxx[p*2+2]);}int query(int p,int l,int r,int x){  if (l>=x) return maxx[p];  int mid=(l+r)>>1;  if (mid<x) return query(p*2+2,mid+1,r,x);    else return max( query(p*2+1,l,mid,x), query(p*2+2,mid+1,r,x) );}int ADD(int x,int flag){  for (int i=x;i<=n;i+=lowbit(i))    tr[i]+=flag;}int GET(int x){  int ret=0;  for (int i=x;i>0;i-=lowbit(i))    ret+=tr[i];  return ret;}int calc(int x){  int ret=0;  for (int l=1,r=n,mid=(l+r)>>1;l<=r;mid=(l+r)>>1){    if (x<=GET(mid)) ret=mid, r=mid-1;      else l=mid+1;  }  return ret;}void add2(int p,int l,int r,int x,bool flag){  if (l==r && l==ht[x]+m){    if (flag) maxx2[p]=dp[x];      else maxx2[p]=0;    return;  }  int mid=(l+r)>>1;  if (ht[x]+m<=mid) add2(p*2+1,l,mid,x,flag);    else add2(p*2+2,mid+1,r,x,flag);  maxx2[p]=max(maxx2[p*2+1],maxx2[p*2+2]);}int query2(int p,int l,int r,int x){  if (l>=x) return maxx2[p];  int mid=(l+r)>>1;  if (x>mid) return query2(p*2+2,mid+1,r,x);    else return max( query2(p*2+1,l,mid,x), query2(p*2+2,mid+1,r,x) );}int main(){  //freopen("264E.in","r",stdin);  //freopen("264E.out","w",stdout);  scanf("%d%d",&n,&m);  M=m+10;  for (tim=1;tim<=m;tim++){    for (I=c.begin();I!=c.end();I++)      if (ht[*I]+tim>10)        {add(0,1,n+1,*I); c.erase(I); break;}    scanf("%d",&typ);        if (typ==1){      scanf("%d",&x);      scanf("%d",&ht[x]);      ht[x]-=tim;      ADD(x, 1);      c.push_back(x);      c.sort();            dp[x]=query(0,1,n+1,x+1)+1;      I=find(c.begin(),c.end(),x);      for (I++;I!=c.end();I++)        if (ht[*I]>ht[x])          dp[x]=max(dp[x],dp[*I]+1);            I=find(c.begin(),c.end(),x);      if (I!=c.begin())      for (I--;;I--){        for (J=I,J++;J!=c.end();J++)          if (ht[*I]<ht[*J])            dp[*I]=max(dp[*I],dp[*J]+1);        if (GET(*I)>10) add2(0,1,M,*I,1);        if (I==c.begin()) break;      }            if (GET(n)>10){        if (GET(x)<=10) add2(0,1,M,calc(11),1);          else add2(0,1,M,x,1);      }          } else    if (typ==2){      scanf("%d",&y);      x=calc(y); ADD(x, -1);      if (GET(n)>=10)        add2(0,1,M,calc(10),0);      I=find(c.begin(),c.end(),x);      dp[x]=0;      if (I==c.end()) add(0,1,n+1,x);        else c.erase(I);            //calc it again      for (i=1;i<y;i++){        x=calc(i);        dp[x]=query2(0,1,M,ht[x]+m)+1;      }      for (i=y-1;i>0;i--){        x=calc(i);        for (j=i+1;j<=10;j++){          xx=calc(j);          if (ht[x]<ht[xx])            dp[x]=max(dp[x],dp[xx]+1);        }        if (ht[x]+tim>10)          add(0,1,n+1,x);      }          }    ans=query(0,1,n+1,1);    for (I=c.begin();I!=c.end();I++)      if (ans<dp[*I]) ans=dp[*I];    printf("%d\n",ans);        //for (i=1;i<=tim;i++)    //  printf("%d ",ht[ calc(i) ]+tim);    //printf("\n");    //printf("%d\n",calc(3));  }  return 0;}


0 0
原创粉丝点击