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
1 1 4 2 3 1 2 5
PushUp函数和query函数是关键 ,PushUp函数向上更新时,先将lsum[rt]用
lsum[rt<<1]也就是左子区间左边开始的最大长度,如果这个区间长度刚好是l到mid之间的长度,说明区间已经穿过中点了,应该
在加上右子区间lsum[rt<<1|1]这部分,类似的可以更新rsum[rt]。对于sum[rt]应该对应rsum[rt<<1]+lsum[rt<<1|1],
sum[rt<<1],sum[rt<<1|1]三种情况中的最大值,因为满足条件的最长单调区间可以是左半部分,右半部分,或者贯穿中点。
理解了这部分那么query函数可以按照类似的思路来写,但要注意的是对于贯穿中点的判断条件是A[mid]<A[mid+1],这样才能
将两部分加起来。
#include <cstdio> #include <cmath> #include <algorithm> #include <iostream> #include <cstring> #include <map> #include <string> #include <stack> #include <cctype> #include <vector> #include <queue> #include <set> #include <utility> using namespace std; //#define Online_Judge #define outstars cout << "***********************" << endl; #define clr(a,b) memset(a,b,sizeof(a)) #define lson l , mid , rt << 1 #define rson mid + 1 , r , rt << 1 | 1 #define mk make_pair #define FOR(i , x , n) for(int i = (x) ; i < (n) ; i++) #define FORR(i , x , n) for(int i = (x) ; i <= (n) ; i++) #define REP(i , x , n) for(int i = (x) ; i > (n) ; i--) #define REPP(i ,x , n) for(int i = (x) ; i >= (n) ; i--) const int MAXN = 100000 + 500; const long long LLMAX = 0x7fffffffffffffffLL; const long long LLMIN = 0x8000000000000000LL; const int INF = 0x7fffffff; const int IMIN = 0x80000000; #define eps 1e-8 #define mod 1000000007 typedef long long LL; const double PI = acos(-1.0); typedef double D; typedef pair<int , int> pi; ///#pragma comment(linker, "/STACK:102400000,102400000") int A[MAXN] , sum[MAXN << 2] , lsum[MAXN << 2] , rsum[MAXN << 2] , n , T , m , a , b; void pushup(int rt , int len , int mid) { lsum[rt] = lsum[rt << 1]; rsum[rt] = rsum[rt << 1 | 1]; int t = 1; if(A[mid] < A[mid + 1]) { if(lsum[rt] == len - (len >> 1)) { lsum[rt] += lsum[rt << 1 | 1]; } if(rsum[rt] == len >> 1) { rsum[rt] += rsum[rt << 1]; } t = lsum[rt << 1| 1] + rsum[rt << 1]; } sum[rt] = max(t , max(sum[rt << 1] , sum[rt << 1 | 1])); } void build(int l , int r , int rt) { if(l == r) { sum[rt] = lsum[rt] = rsum[rt] = 1; return ; } int mid = (l + r) >> 1; build(lson);build(rson); pushup(rt , r - l + 1 , mid); } void update(int p , int l , int r, int rt) { if(l == r)return ; int mid = (l + r) >> 1; if(p <= mid)update(p , lson); else update(p , rson); pushup(rt , r - l + 1 , mid); } int query(int L , int R , int l , int r ,int rt) { if(L <= l&& r <= R)return sum[rt]; int mid = (l + r) >> 1; if(l == r)return 1; int ans = 0; if(R <= mid)ans = max(ans , query(L , R , lson)); else if (L > mid)ans = max(ans , query(L ,R , rson)); else { ans = max(ans , query(L ,R , lson)); ans = max(ans , query(L ,R , rson)); int ll , rr; if(mid - L + 1 >= rsum[rt << 1]) { ll = rsum[rt << 1]; } else ll = mid - L + 1; if(R - mid >= lsum[rt << 1 | 1]) { rr = lsum[rt << 1 | 1]; } else rr = R - mid; ans = max(ans , max(ll , rr)); if(A[mid] < A[mid + 1]) { ans = max(ans ,ll + rr); } } return ans; } int main() { //ios::sync_with_stdio(false); #ifdef Online_Judge freopen("in.txt","r",stdin); freopen("out.txt","w",stdout); #endif // Online_Judge cin >> T; while(T--) { scanf("%d%d" , &n , &m); FORR(i , 1 , n)scanf("%d" , &A[i]); build(1 , n , 1); char s[5]; while(m--) { scanf("%s%d%d" , s ,&a , &b); if(s[0] == 'U') { A[a + 1] = b; update(a + 1 , 1 , n , 1); } else { int ans = query(a + 1 , b + 1 , 1 ,n , 1); printf("%d\n" , ans); } } } return 0; }