LCIS HDU - 3308 (线段树区间合并)

LCIS HDU - 3308 

Given 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<=10 5). 
The next line has n integers(0<=val<=10 5). 
The next m lines each has an operation: 
U A B(0<=A,n , 0<=B=10 5
OR 
Q A B(0<=A<=B< n). 
OutputFor each Q, output the answer.Sample Input

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

Sample Output

1
1
4
2
3
1
2
5
个人思路:这道题应该算是线段树区间合并的板子题,关键就是明确区间合并时的逻辑关系就可以了
我因为忽略区间内的最长连续上升序列有可能由子区间的区间内连续上升序列得到而错了好几次
  1 //线段树区间合并
  2 //关键:明确相邻区间合并时候的逻辑关系
  3 #include<bits/stdc++.h>
  4 #define ios ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
  5 #define mem(a,x) memset(a,x,sizeof(a))
  6 #define lson rt<<1,l,mid
  7 #define rson rt<<1|1,mid + 1,r
  8 #define P pair<int,int>
  9 #define ull unsigned long long
 10 using namespace std;
 11 typedef long long ll;
 12 const int maxn = 1e5 + 10;
 13 const int inf = 0x3f3f3f3f;
 14 
 15 struct node
 16 {
 17     int l,r;
 18     int left ,right ,mid;
 19     int maxx;
 20 }tree[maxn << 2];
 21 
 22 int n,m;
 23 int arr[maxn];
 24 
 25 void Pushup(int rt)
 26 {
 27     tree[rt].left = tree[rt << 1].left;
 28     tree[rt].right = tree[rt << 1|1].right;
 29     bool flag = arr[tree[rt << 1|1].l] > arr[tree[rt << 1].r];
 30 
 31     if(tree[rt << 1|1].right == tree[rt << 1|1].r - tree[rt << 1|1].l + 1 && flag)
 32     {
 33         tree[rt].right += tree[rt << 1].right;
 34     }
 35     // 合并以左端点为头的最长序列
 36     
 37     if(tree[rt << 1].left == tree[rt << 1].r - tree[rt << 1].l + 1 && flag)
 38     {
 39         tree[rt].left += tree[rt << 1|1].left;
 40     }
 41     // 合并以右端点为尾的最长序列
 42     
 43     if(arr[tree[rt << 1|1].l] > arr[tree[rt << 1].r])
 44     {
 45         tree[rt].mid = tree[rt << 1].right + tree[rt << 1|1].left;
 46     }
 47     else
 48     {
 49         tree[rt].mid = max(tree[rt << 1].right , tree[rt << 1|1].left);
 50     }
 51     tree[rt].mid = max(tree[rt].mid , max(tree[rt << 1].mid,tree[rt << 1|1].mid)); 
 52     // 获得区间内的最长序列:可能由子区间构成 也可能从子区间得到
 53     tree[rt].maxx = max(tree[rt].mid, max(tree[rt].left , tree[rt].right));
 54 }
 55 
 56 void build(int rt ,int l ,int r)
 57 {
 58     tree[rt].l = l , tree[rt].r = r;
 59     if(l == r)
 60     {
 61         tree[rt].left = tree[rt].right = tree[rt].maxx = tree[rt].mid = 1;
 62         return;
 63     }
 64     int mid = l + r >> 1;
 65     build(lson);
 66     build(rson);
 67     Pushup(rt);
 68 }
 69 
 70 void update(int rt ,int k ,int v)
 71 {
 72     if(tree[rt].l == k && tree[rt].r == k)
 73     {
 74         arr[k] = v;
 75         tree[rt].left = tree[rt].right = tree[rt].maxx = tree[rt].mid = 1;
 76         return;
 77     }
 78     int mid = tree[rt].l + tree[rt].r >> 1;
 79     if(mid >= k)
 80     {
 81         update(rt << 1 , k , v);
 82     }
 83     else
 84     {
 85         update(rt << 1|1 , k , v);
 86     }
 87     Pushup(rt);
 88 }
 89 
 90 int query(int rt , int l ,int r)
 91 {
 92     if(tree[rt].l == l && tree[rt].r == r)
 93     {
 94         return tree[rt].maxx;
 95     }
 96     int mid = tree[rt].l + tree[rt].r >> 1;
 97     if(mid >= r)
 98     {
 99         return query(rt << 1, l , r);
100     }
101     else if(mid < l )
102     {
103         return query(rt << 1|1 , l , r);
104     }
105     else
106     {
107         int m = min(mid - l + 1 , tree[rt << 1].right) + min(r - mid , tree[rt << 1|1].left);
108         int left = query(rt<<1 ,l ,mid);
109         int right = query(rt << 1|1 , mid + 1 , r);
110         if(arr[tree[rt << 1].r] < arr[tree[rt << 1|1].l])
111         {
112             return max(m,max(left , right));
113         }
114         else
115         {
116             return max(left , right);
117         }
118     }
119 }
120 
121 
122 int main()
123 {
124     int T;
125     scanf("%d",&T);
126     while(T--)
127     {
128         //mem(arr,0);
129         scanf("%d %d",&n,&m);
130         for(int i = 1 ; i <= n ; ++ i)
131         {
132             scanf("%d",&arr[i]);
133         }
134         build(1,1,n);
135         while(m -- )
136         {
137             char judge;
138             int l,r;
139             scanf(" %c %d %d",&judge ,&l , &r);
140             if(judge == 'U')
141             {
142                 update(1,l + 1,r);
143             }
144             else
145             {
146                 printf("%d\n",query(1,l + 1, r + 1));
147             }
148         }
149     }
150     return 0;
151 }
AC代码

一个从很久以前就开始做的梦

posted @ 2019-09-11 17:57  当然是斗笠呀  阅读(152)  评论(0编辑  收藏  举报