HDU 3308 線段樹(區間合并)

來源:互聯網
上載者:User

標籤:des   style   blog   java   color   os   

LCIS

Time Limit: 6000/2000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 3896    Accepted Submission(s): 1766


Problem DescriptionGiven n integers.
You have two operations:
U A B: replace the Ath number by B. (index counting from 0)
Q A B: output the length of the longest consecutive increasing subsequence (LCIS) in [a, b]. 

 

InputT in the first line, indicating the case number.
Each case starts with two integers n , m(0<n,m<=105).
The next line has n integers(0<=val<=105).
The next m lines each has an operation:
U A B(0<=A,n , 0<=B=105)
OR
Q A B(0<=A<=B< n). 

 

OutputFor each Q, output the answer. 

 

Sample Input110 107 7 3 3 5 9 9 8 1 8 Q 6 6U 3 4Q 0 1Q 0 5Q 4 7Q 3 5Q 0 2Q 4 6U 6 10Q 0 9 

 

Sample Output11423125     題目意思:給兩個數字n,m,分別代表數組長度和操作次數,下面一行是長度為n的序列,下面m行操作,共有兩種操作:U a b 是把數組中a位置處的數字變為b(單點更新),Q a b  是輸出區間[a,b]的最長連續子序列額長度。  典型的線段樹區間合并了,其實我比較煩區間合并,考慮的條件有點多,稍不注意就錯了,首先分析線段樹結點所含元素種類:一個區間有左邊界和右邊界為l,r(線段樹必不可少的),記錄最長連續子序列的長度len,由於單點更新的時候區間的最長連續子序列的長度len可能發生變化,由子區間推出母區間,所以需要兩個元素lmax,rmax即為區間包含左邊界的連續子序列的長度、包含右邊界的連續子序列的長度。 結點所含的元素種類確定下來了,就該進行操作了,建樹就不說了(看代碼吧),主要說一下up(向上更新)和query(輸出) 。up: 一個結點root的lmax和rmax顯然分別等於左兒子的lmax和右兒子的rmax,len一會再說,怎麼合并呢?當左兒子的右邊界的值小於右兒子的左邊界的值時,(在之前條件的情況下)如果左兒子的lmax包括了其右邊界,那麼root的lmax需要更新為tree[root*2].lmax+a[root*2+1].lmax,同理如果右兒子的rmax包括其左邊界,那麼root的rmax需要更新為tree[root*2+1].rmax+tree[root*2].rmax,  root的len  可能誕生在左邊、右邊、中間,那麼取最大即可。 query: 主要講一下所求的區間[a,b]既包含root的左兒子又包含其右兒子,那麼可以用記憶話搜尋用ln,rn分別記錄root的左兒子和右兒子,區間[a,b]最長連續子序列可能誕生在ln中、rn中、或者ln和rn中,前兩種情況好說,主要是最後一種,需要區間合并,合并方法和up函數同出一轍。 下面看代碼:
  1 #include <cstdio>  2 #include <cstring>  3 #include <algorithm>  4 #include <iostream>  5 using namespace std;  6 #define N 100005  7 #define ll root*2  8 #define rr root*2+1  9  10 int num[N]; 11 int n, m; 12  13  14 struct node{ 15     int l, r; 16     int lmax, rmax; 17     int len; 18 }a[N*4]; 19  20  21 void pushup(int root){ 22     if(a[root].l==a[root].r) return; 23     a[root].lmax=a[ll].lmax; 24     a[root].rmax=a[rr].rmax; 25     a[root].len=max(a[ll].len,a[rr].len); 26      27     if(num[a[ll].r]<num[a[rr].l]){ 28         if(a[ll].lmax==(a[ll].r-a[ll].l+1)) a[root].lmax=a[ll].lmax+a[rr].lmax; 29         if(a[rr].rmax==(a[rr].r-a[rr].l+1)) a[root].rmax=a[rr].rmax+a[ll].rmax; 30         a[root].len=max(max(a[root].len,a[ll].rmax+a[rr].lmax),max(a[root].lmax,a[root].rmax)); 31     } 32 } 33  34 void build(int left,int right,int root){ 35     a[root].l=left; 36     a[root].r=right; 37     if(left==right){ 38         a[root].len=1; 39         a[root].lmax=a[root].rmax=1; 40         return ; 41     } 42     int mid=(left+right)/2; 43     build(left,mid,root*2); 44     build(mid+1,right,root*2+1); 45     pushup(root); 46 } 47  48 void update(int p,int val,int root){ 49     if(a[root].l==p&&a[root].r==p){ 50         num[p]=val; 51         return ; 52     } 53     int mid=(a[root].l+a[root].r)/2; 54     if(p<=mid) update(p,val,ll); 55     else update(p,val,rr); 56     pushup(root); 57 } 58  59 node query(int left,int right,int root){ 60     node n1, l1, r1; 61     if(a[root].l==left&&a[root].r==right){ 62         n1.lmax=a[root].lmax; 63         n1.rmax=a[root].rmax; 64         n1.len=a[root].len; 65         return n1; 66     } 67     if(left>=a[rr].l) return query(left,right,rr); 68     else if(right<=a[ll].r) return query(left,right,ll); 69     else{                                               //所求的連續子序列在中間,需要區間合并  70         int mid=(a[root].l+a[root].r)/2; 71         l1=query(left,mid,ll); 72         r1=query(mid+1,right,rr); 73         n1.lmax=l1.lmax; 74         n1.rmax=r1.rmax; 75         n1.len=max(l1.len,r1.len); 76         if(num[mid]<num[mid+1]){ 77             if(l1.lmax==(mid-left+1)) n1.lmax+=r1.lmax; 78             if(r1.rmax==(right-mid)) n1.rmax+=l1.rmax; 79             n1.len=max(max(n1.len,l1.rmax+r1.lmax),max(n1.lmax,n1.rmax)); 80         } 81         return n1; 82     } 83 } 84  85 main() 86 { 87     int t, i, j, k, x, y; 88     char c[5]; 89     cin>>t; 90     while(t--){ 91         cin>>n>>m; 92         for(i=1;i<=n;i++) scanf("%d",&num[i]); 93         build(1,n,1); 94         while(m--){ 95              96             scanf("%s %d %d",c,&x,&y); 97             if(strcmp(c,"U")==0){ 98                 update(x+1,y,1); 99             }100             else{101                 printf("%d\n",query(x+1,y+1,1).len);102             }103         }104     }105 }

 

  

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.