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].
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 ",query(1,l + 1, r + 1)); 147 } 148 } 149 } 150 return 0; 151 }
一个从很久以前就开始做的梦