uestc 1425 Another LCIS(成段更新)

来源:互联网 发布:抗日主力的真相 知乎 编辑:程序博客网 时间:2024/05/09 10:15

题意:有T(t<10)组数据,给你N个数,M个操作(N和M都小于100000)。操作有两种类型,(1)“q a b”,查询区间[a,b]里的最长连续上升序列的长度。(2)“a l r v”,将区间[l,r]里的数全部增加v。

         要记录区间里的最长的序列长度是多少,用mx来记录。由于最长的连续上升序列可以在区间的左端点,右端点,所以在线段树里增加两个域lmx和rmx,分别表示,在区间的端点处,分别向右向左的最长的满足条件的序列长度。但是还有可能出现在中间,所以又增加两个域lval和rval,分别表示区间端点的值是多少。合并的时候,判断左儿子的rval是否小于右儿子lval,如果满足,这个区间的mx可能为左儿子的rmx加上右儿子的lmx。另外,这个区间的mx可能是左儿子的mx或者右儿子的mx。
        在更新当前区间的lmx时,如果左子区间的lmx等于左子区间的长度,那么当前区间的lmx就要加上右儿子的lmx。更新当前区间的rmx时同理。
        另外在查询的时候,要注意,有可能当前区间的lmx大于mid-st+1,所以要在其中取一个较小值,同理rmx有可能大于ed-mid。

#include <iostream>  #include <cstdio>  #include <cstring>  using namespace std;  #define LL(x) (x<<1)  #define RR(x) (x<<1|1)  #define MID(a,b) (a+((b-a)>>1))  const int N=100005;  struct node  {      int lft,rht;      int lmx,rmx,mx;      int lval,rval,add;      void fun(int tmp)      { add+=tmp; lval+=tmp; rval+=tmp; }      int len(){return rht-lft+1;}      int mid(){return MID(lft,rht);}      void init(){ lmx=rmx=mx=add=0; }  };    int y[N],n,m;    struct Segtree  {      node tree[N*4];      void down(int ind)      {          if(tree[ind].add)          {              tree[LL(ind)].fun(tree[ind].add);              tree[RR(ind)].fun(tree[ind].add);              tree[ind].add=0;          }      }      void up(int ind)      {          tree[ind].lmx=tree[LL(ind)].lmx;          tree[ind].rmx=tree[RR(ind)].rmx;          tree[ind].lval=tree[LL(ind)].lval;          tree[ind].rval=tree[RR(ind)].rval;          tree[ind].mx=max(tree[LL(ind)].mx,tree[RR(ind)].mx);            if(tree[LL(ind)].rval<tree[RR(ind)].lval)          {              if(tree[LL(ind)].lmx==tree[LL(ind)].len())                  tree[ind].lmx+=tree[RR(ind)].lmx;              if(tree[RR(ind)].rmx==tree[RR(ind)].len())                  tree[ind].rmx+=tree[LL(ind)].rmx;              tree[ind].mx=max(tree[ind].mx,tree[LL(ind)].rmx+tree[RR(ind)].lmx);          }          tree[ind].mx=max(tree[ind].mx,max(tree[ind].lmx,tree[ind].rmx));      }      void build(int lft,int rht,int ind)      {          tree[ind].lft=lft;  tree[ind].rht=rht;          tree[ind].init();          if(lft==rht)          {              tree[ind].lval=tree[ind].rval=y[lft];              tree[ind].lmx=tree[ind].rmx=tree[ind].mx=1;          }          else          {              int mid=tree[ind].mid();              build(lft,mid,LL(ind));              build(mid+1,rht,RR(ind));              up(ind);          }      }      void updata(int st,int ed,int ind,int valu)      {          int lft=tree[ind].lft,rht=tree[ind].rht;          if(st<=lft&&rht<=ed) tree[ind].fun(valu);          else          {              down(ind);              int mid=tree[ind].mid();              if(st<=mid) updata(st,ed,LL(ind),valu);              if(ed> mid) updata(st,ed,RR(ind),valu);              up(ind);          }      }      int query(int st,int ed,int ind)      {          int lft=tree[ind].lft,rht=tree[ind].rht;          if(st<=lft&&rht<=ed) return tree[ind].mx;          else          {              down(ind);              int mid=tree[ind].mid();              if(ed<=mid) return query(st,ed,LL(ind));              else if(st>mid) return query(st,ed,RR(ind));              else              {                  int mid=tree[ind].mid();                  int mx1=query(st,ed,LL(ind));                  int mx2=query(st,ed,RR(ind));                  int tmp1=0,tmp2=0;                  if(tree[LL(ind)].rval<tree[RR(ind)].lval)                  {                      tmp1=min(mid-st+1,tree[LL(ind)].rmx);                      tmp2=min(ed-mid,tree[RR(ind)].lmx);                  }                  return max(max(mx1,mx2),tmp1+tmp2);              }          }      }  }seg;  int main()  {      int t,t_cnt=0;      scanf("%d",&t);      while(t--)      {          char str[10];          int a,b,c;            scanf("%d%d",&n,&m);          for(int i=1;i<=n;i++) scanf("%d",&y[i]);          seg.build(1,n,1);            printf("Case #%d:\n",++t_cnt);          while(m--)          {              scanf("%s",str);              if(str[0]=='q')              {                  scanf("%d%d",&a,&b);                  printf("%d\n",seg.query(a,b,1));              }              else              {                  scanf("%d%d%d",&a,&b,&c);                  seg.updata(a,b,1,c);              }          }      }      return 0;  }  


原创粉丝点击