zoukankan      html  css  js  c++  java
  • UESTC 360(1425) another LCIS

    这道题是CD老OJ上面的一道题,现在在新OJ上的题号是360,开始在VJ上做的提交一直RE(囧)。后来才知道OJ移位了。

    这道题是一个简单的成段更新+区间合并的线段树的题,1A还让我小激动了一下

    这道题的大概意思是有两种操作,一种是成段地增加一个值,另外一种是询问从l到r这段区间内的最长递增子序列

    首先先分析一下,如果某一段的值成段地增加一个量,那么该区间内的数的相对大小是不变的,因此递增子序列的长度是不会改变的

    是要分析对于结果有影响的信息与值:一是每个子区间中的最值,二是有可能在两个区间合并之后的两个区间的中间的两段成为新的最值,因此我们需要判断中间的两个值是否可以合并,从何得知:我们需要在运算过程中分别记录下左端点的值和右端点的值,来判断是否可以合并。因此在每个节点增设两个值lv,rv。

    还有一个问题就是在查询过程中,可能会存在查询的范围R-mid比lsum[rt<<1|1]小(mid-L+1比rsum[rt<<1]小),因此用比较取较小值相加就OK;额

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 using namespace std;
     5 const int SIZEN=100005;
     6 int sum[SIZEN<<2],lsum[SIZEN<<2],rsum[SIZEN<<2];
     7 int lv[SIZEN<<2],rv[SIZEN<<2],add[SIZEN<<2];
     8 int a[SIZEN];
     9 void pushup(int len,int rt){
    10     int tmp;
    11     lsum[rt]=lsum[rt<<1];
    12     rsum[rt]=rsum[rt<<1|1];
    13     lv[rt]=lv[rt<<1];rv[rt]=rv[rt<<1|1];
    14     if(lsum[rt]==(len-(len>>1))&&rv[rt<<1]<lv[rt<<1|1]) lsum[rt]+=lsum[rt<<1|1];
    15     if(rsum[rt]==(len>>1)&&rv[rt<<1]<lv[rt<<1|1]) rsum[rt]+=rsum[rt<<1];
    16     tmp=rsum[rt<<1]+lsum[rt<<1|1];
    17     if(rv[rt<<1]<lv[rt<<1|1])
    18         sum[rt]=max(tmp,max(sum[rt<<1],sum[rt<<1|1]));
    19     else sum[rt]=max(sum[rt<<1],sum[rt<<1|1]);
    20 }
    21 void pushdown(int rt){
    22     if(add[rt]!=0){
    23         add[rt<<1]+=add[rt];
    24         add[rt<<1|1]+=add[rt];
    25         lv[rt<<1]+=add[rt];rv[rt<<1]+=add[rt];
    26         lv[rt<<1|1]+=add[rt];rv[rt<<1|1]+=add[rt];
    27         add[rt]=0;
    28     }
    29 }
    30 void update(int L,int R,int o,int l,int r,int rt){
    31     if(L<=l&&r<=R){
    32         add[rt]+=o;
    33         lv[rt]+=o;rv[rt]+=o;
    34         return;
    35     }
    36     pushdown(rt);
    37     int mid=(l+r)>>1;
    38     if(L<=mid) update(L,R,o,l,mid,rt<<1);
    39     if(mid+1<=R) update(L,R,o,mid+1,r,rt<<1|1);
    40     pushup(r-l+1,rt);
    41 }
    42 void build(int l,int r,int rt){
    43     add[rt]=0;
    44     if(l==r){
    45         sum[rt]=lsum[rt]=rsum[rt]=1;
    46         lv[rt]=rv[rt]=a[l];
    47         return;
    48     }
    49     int mid=(l+r)>>1;
    50     build(l,mid,rt<<1);
    51     build(mid+1,r,rt<<1|1);
    52     pushup(r-l+1,rt);
    53 }
    54 int query(int L,int R,int l,int r,int rt){
    55     if(L<=l&&r<=R){
    56         return sum[rt];
    57     }
    58     int mid=(l+r)>>1,r1,r2,r3;
    59     int len=r-l+1;
    60     r1=r2=r3=-1;
    61     pushdown(rt);
    62     if(L<=mid) r1=query(L,R,l,mid,rt<<1);
    63     if(mid+1<=R) r2=query(L,R,mid+1,r,rt<<1|1);
    64     if(rv[rt<<1]<lv[rt<<1|1]) r3=min(rsum[rt<<1],mid-L+1)+min(lsum[rt<<1|1],R-mid);
    65     return max(r1,max(r2,r3));
    66 }
    67 int main()
    68 {
    69     //freopen("data.in","r",stdin);
    70     int i,j,_;
    71     char c;
    72     int l,r,o;
    73     int n,q,txt=1;
    74     scanf("%d",&_);
    75     while(_--){
    76         printf("Case #%d:
    ",txt++);
    77         scanf("%d%d",&n,&q);
    78         for(i=1;i<=n;i++)
    79             scanf("%d",&a[i]);
    80         build(1,n,1);
    81         while(q--){
    82             scanf(" %c",&c);
    83             if(c=='a'){
    84                 scanf("%d%d%d",&l,&r,&o);
    85                 update(l,r,o,1,n,1);
    86             }
    87             else{
    88                 scanf("%d%d",&l,&r);
    89                 int ret=query(l,r,1,n,1);
    90                 printf("%d
    ",ret);
    91             }
    92         }
    93     }
    94     return 0;
    95 }
  • 相关阅读:
    新增访客数量MR统计之NewInstallUserMapper相关准备
    新增访客数量MR统计之NewInstallUserMapper中维度信息准备
    编译器编译原理理解
    构造函数的理解和应用场景
    大小字节序的深入理解和鉴定系统字节序方法
    定义结构体和初始化的方法
    Source Insight 光标变粗设置NotePad++光标设置
    栈实现java
    快速排序java
    希尔排序java
  • 原文地址:https://www.cnblogs.com/acalvin/p/3702368.html
Copyright © 2011-2022 走看看