首先线段树每一个节点包含:[b,e],lmax,rmax,max;其中lmax表示从左端点开始连续的最长的增序列长度,rmax表示从e端点开始向左连续的最长下降序列长度,max表示当前区间的连续递增的最长序列长度。对单个节点插入时的信息维护如下:
(1) if 左儿子的右端点的值<右儿子的左端点的值
lmax=左儿子区间长度==左儿子的lmax?左儿子区间长度+右儿子的lmax:左儿子的lmax.
rmax=右儿子区间长度==右儿子的rmax?右儿子区间长度+左儿子的rmax:右儿子的rmax.
max=MAX(lmax,rmax,左儿子的rmax+右儿子的lmax);
(2)否则
lmax=左儿子的lmax;
rmax=右儿子的rmax;
max=MAX(左儿子的max,右儿子的max);
查寻操作如下:
if 当前节点区间==查询区间
返回当前节点的max
否则
返回 MAX(左区间,右区间,跨越边界的长度)
//------------------------------------------------------------------ //---线段树区间更新 #define _CRT_SECURE_NO_DEPRECATE #include<iostream> #include<algorithm> using namespace std; const int MAXN = 1000000; struct Tnode{ int b, e; int lmax; int rmax; int max; int len(){ return e - b + 1; } }; Tnode tree[4*MAXN]; int p[MAXN]; int n, m; int max(int a, int b, int c){ return max(max(a, b), c); } void Build(int v, int l, int r){ tree[v].b = l, tree[v].e = r; tree[v].lmax = tree[v].rmax = tree[v].max = 0; if (l < r){ int mid = (l + r) >> 1; Build(2 * v + 1, l, mid); Build(2 * v + 2, mid + 1, r); } } void Insert(int v, int k, int val){ if (tree[v].b == tree[v].e){ //找到叶节点插入 p[k] = val; tree[v].lmax = tree[v].rmax = tree[v].max = 1; return; } int mid = (tree[v].b + tree[v].e) >> 1; if (k <= mid) Insert(2 * v + 1, k, val); else Insert(2 * v + 2, k, val); //接下来更新 if (p[mid] < p[mid + 1]){ if (tree[2 * v + 1].lmax == tree[2 * v + 1].len()) tree[v].lmax = tree[2 * v + 1].len() + tree[2 * v + 2].lmax; else tree[v].lmax = tree[2*v+1].lmax; if (tree[2 * v + 2].rmax == tree[2 * v + 2].len()) tree[v].rmax = tree[2 * v + 2].len() + tree[2 * v + 1].rmax; else tree[v].rmax = tree[2*v+2].rmax; tree[v].max = max(tree[2 * v + 1].max, tree[2 * v + 2].max,tree[2 * v + 1].rmax + tree[2 * v + 2].lmax); } else{ tree[v].lmax = tree[2*v+1].lmax; tree[v].rmax = tree[2 * v + 2].rmax; tree[v].max = max(tree[2 * v + 1].max,tree[2 * v + 2].max); } } int Qurrey(int v,int l, int r){ if (l == tree[v].b&&r == tree[v].e) return tree[v].max; int mid = (tree[v].b + tree[v].e) >> 1; if (r <= mid) return Qurrey(2 * v + 1, l, r); else if (l > mid) return Qurrey(2 * v + 2, l, r); else{ if (p[mid] < p[mid + 1]){ int left = max(mid + 1 - tree[2 * v + 1].rmax, l); int right = min(r, mid + tree[2 * v + 2].lmax); return max(Qurrey(2 * v + 1, l, mid), Qurrey(2 * v + 2, mid + 1, r), right-left+1); } else return max(Qurrey(2 * v + 1, l, mid), Qurrey(2 * v + 2, mid + 1, r)); } } int main(){ int i, T,a,b; char s; scanf("%d", &T); while (T--){ scanf("%d%d", &n, &m); memset(p, 0, sizeof(p)); Build(0, 0, n - 1); for (i = 0; i < n; i++){ scanf("%d", &p[i]); Insert(0, i, p[i]); } while (m--){ cin >> s; scanf("%d%d",&a, &b); if (s == ‘U‘) Insert(0, a, b); else printf("%d\n", Qurrey(0, a, b)); } } return 0; }
时间: 2024-10-24 20:48:05