UESTC 360(1425) another LCIS

這道題是CD老OJ上面的一道題,如今在新OJ上的題號是360,開始在VJ上作的提交一直RE(囧)。後來才知道OJ移位了。ui

這道題是一個簡單的成段更新+區間合併的線段樹的題,1A還讓我小激動了一下spa

這道題的大概意思是有兩種操做,一種是成段地增長一個值,另一種是詢問從l到r這段區間內的最長遞增子序列code

首先先分析一下,若是某一段的值成段地增長一個量,那麼該區間內的數的相對大小是不變的,所以遞增子序列的長度是不會改變的blog

是要分析對於結果有影響的信息與值:一是每一個子區間中的最值,二是有可能在兩個區間合併以後的兩個區間的中間的兩段成爲新的最值,所以咱們須要判斷中間的兩個值是否能夠合併,從何得知:咱們須要在運算過程當中分別記錄下左端點的值和右端點的值,來判斷是否能夠合併。所以在每一個節點增設兩個值lv,rv。string

還有一個問題就是在查詢過程當中,可能會存在查詢的範圍R-mid比lsum[rt<<1|1]小(mid-L+1比rsum[rt<<1]小),所以用比較取較小值相加就OK;額it

 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:\n",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\n",ret);
91             }
92         }
93     }
94     return 0;
95 }
相關文章
相關標籤/搜索