题意 : 求最长连续递增序列,10^5次操作。
思路 : 线段树区间合并实现。因为只是求连续的,所以只要记录每个区间左边起和右边结束还有最大的3个LCIS值,然后合并相应区间就行。
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn = 100005;
int max(int a,int b){return a > b ? a : b;}
#define lson rt<<1, l, mid
#define rson rt<<1|1, mid+1, r
struct seg
{
int l,r,lv,rv;
}rsum[maxn<<2],lsum[maxn<<2],sum[maxn<<2];
struct GOD
{
seg ll, mm, rr;
};
int n, m;
int get(seg x)
{
return x.r - x.l + 1;
}
void pushup(int rt, int M)
{
lsum[rt] = lsum[rt<<1]; rsum[rt] = rsum[rt<<1|1];
if (get(lsum[rt<<1]) == M - (M>>1) && lsum[rt<<1].rv < lsum[rt<<1|1].lv)
{
lsum[rt].r = lsum[rt<<1|1].r;
lsum[rt].rv = lsum[rt<<1|1].rv;
}
if (get(rsum[rt<<1|1]) == (M>>1) && rsum[rt<<1|1].lv > rsum[rt<<1].rv)
{
rsum[rt].l = rsum[rt<<1].l;
rsum[rt].lv = rsum[rt<<1].lv;
}
sum[rt] = (get(sum[rt<<1]) > get(sum[rt<<1|1]) ? sum[rt<<1] : sum[rt<<1|1]);
if (rsum[rt<<1].rv < lsum[rt<<1|1].lv && get(rsum[rt<<1]) + get(lsum[rt<<1|1]) > get(sum[rt]))
{
sum[rt].l = rsum[rt<<1].l; sum[rt].lv = rsum[rt<<1].lv;
sum[rt].r = lsum[rt<<1|1].r; sum[rt].rv = lsum[rt<<1|1].rv;
}
}
void build(int rt, int l, int r)
{
if (l == r)
{
int a;
scanf("%d",&a);
sum[rt].l = sum[rt].r = l;
sum[rt].lv = sum[rt].rv = a;
lsum[rt] = rsum[rt] = sum[rt];
return ;
}
int mid = (l + r) >> 1;
build(lson); build(rson);
pushup(rt, r - l + 1);
}
void update(int rt, int l, int r, int p, int v)
{
if (l == r)
{
sum[rt].lv = sum[rt].rv = v;
lsum[rt] = rsum[rt] = sum[rt];
return ;
}
int mid = (l + r) >> 1;
if (mid >= p)update(lson, p, v);
else update(rson, p, v);
pushup(rt, r - l + 1);
}
GOD hebing(GOD a, GOD b)
{
GOD res;
res.ll = a.ll; res.rr = b.rr;
if (a.rr.rv < b.ll.lv && get(a.rr) + get(b.ll) > max(get(a.mm), get(b.mm)))
{
res.mm.r = b.ll.r; res.mm.rv = b.ll.rv;
res.mm.l = a.rr.l; res.mm.lv = a.rr.lv;
}
else
{
res.mm = (get(a.mm) > get(b.mm) ? a.mm : b.mm);
}
if (a.ll.rv < b.ll.lv && a.ll.r == b.ll.l - 1)
{
res.ll.r = b.ll.r;
res.ll.rv = b.ll.rv;
}
if (a.rr.rv < b.rr.lv && b.rr.l == a.rr.r + 1)
{
res.rr.l = a.rr.l;
res.rr.lv = a.rr.lv;
}
return res;
}
GOD query(int rt, int l, int r, int L, int R)
{
GOD res;
if (l >= L && r <= R)
{
res.ll = lsum[rt];
res.rr = rsum[rt];
res.mm = sum[rt];
return res;
}
GOD gg;
res.mm.l = gg.mm.l = -1;
int mid = (l + r) >> 1;
if (mid >= L)
{
res = query(lson, L, R);
}
if (R > mid)
{
if (res.mm.l == -1)
return query(rson, L, R);
else
{
gg = query(rson, L, R);
return hebing(res,gg);
}
}
return res;
}
int main()
{
int T;
scanf("%d",&T);
while (T--)
{
scanf("%d%d",&n,&m);
build(1, 1, n);
while (m--)
{
char op[2];
int a, b;
scanf("%s %d%d",op, &a, &b);
if (op[0] == 'U')
{
update(1, 1, n, a+1, b);
}
else
{
GOD ans = query(1, 1, n, a+1, b+1);
printf("%d\n", get(ans.mm));
}
//printf("%s\n",op);
}
}
return 0;
}