前面还一位这是一道最长上升子序列的题目,只觉得无从下手,后来得知是最长连续上升子序列,于是有了想法。 (英文不好啊,题目中就能看出来的)
对于每一个节点保留其左起及右起连续子序列长度和整个区间的最长连续长度。当然利用这三个信息加之线段树的结构我们就能够得到所要的结果。
先说说我自己的写法(后来证明是写复杂了),对于每个询问我定义了三个状态 0, 1, 2。 0 表示该区间内不需要从左边或者是右边开始计算,1 表示求这段区间的右连续, 2 表示这段区间的左连续,然后就是一连串的分解判断,详见代码。
该题的调试过程多亏了丽丽同学的帮助,自己生成的数据,用别人AC的代码跑结果,然后再和自己的结果比较......
代码如下:
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <algorithm>
#define MAXN 100005
#define L(x) ((x)<<1)
#define R(x) ((x)<<1|1)
using namespace std;
int seq[MAXN];
struct
{
int l, r, lmax, rmax, max;
}seg[MAXN*3];
void creat(int f, int l, int r)
{
int mid = (l+r) >> 1;
// 初始化的地方
seg[f].l = l, seg[f].r = r;
seg[f].lmax = seg[f].rmax = 0;
seg[f].max = 0;
if (r > l)
{
creat(f<<1, l, mid);
creat(f<<1|1, mid+1, r);
}
}
void modify(int f, int pos, int y)
{
int mid = (seg[f].l+seg[f].r)>>1;
if (seg[f].l == seg[f].r)
{
seq[pos] = y;
seg[f].lmax = seg[f].rmax = seg[f].max = 1;
}
else if (seg[f].r > seg[f].l)
{
if (pos <= mid)
modify(f<<1, pos, y);
else if (pos > mid)
modify(f<<1|1, pos, y);
// 非常重要的维护阶段
seg[f].lmax = seg[f<<1].lmax;
seg[f].rmax = seg[f<<1|1].rmax;
if (seg[f<<1].lmax == seg[f<<1].r-seg[f<<1].l+1 && seq[mid]<seq[mid+1])
{
seg[f].lmax += seg[f<<1|1].lmax;
}
if (seg[f<<1|1].rmax == seg[f<<1|1].r-seg[f<<1|1].l+1 && seq[mid]<seq[mid+1])
{
seg[f].rmax += seg[f<<1].rmax;
}
seg[f].max = max(seg[f<<1].max, seg[f<<1|1].max);
// 这里写错了,弄了大半天
if (seq[mid]<seq[mid+1])
seg[f].max = max(seg[f].max, seg[f<<1].rmax+seg[f<<1|1].lmax);
}
}
int query(int f, int l, int r, int way)
{
int mid = (seg[f].l+seg[f].r) >> 1;
if (seg[f].l == l && r == seg[f].r)
{
if (way == 0)
{
return seg[f].max;
}
if (way == 1)
return seg[f].rmax;
else
return seg[f].lmax;
}
else if (seg[f].r > seg[f].l)
{
if (r <= mid)
return query(f<<1, l, r, way);
else if (l > mid)
return query(f<<1|1, l, r, way);
else
{
if (way == 0)
{
int c = max(query(f<<1, l, mid, 0), query(f<<1|1, mid+1, r, 0));
if (seq[mid]<seq[mid+1])
{
c = max(c, query(f<<1, l, mid, 1)+query(f<<1|1, mid+1, r, 2));
}
return c;
}
else if (way == 1)
{
int c = query(f<<1|1, mid+1, r, 1);
if (c == seg[f<<1|1].r-seg[f<<1|1].l+1 && seq[mid]<seq[mid+1])
c += query(f<<1, l, mid, 1);
return c;
}
else
{
int c = query(f<<1, l, mid, 2);
if (c == seg[f<<1].r-seg[f<<1].l+1 && seq[mid]<seq[mid+1])
c += query(f<<1|1, mid+1, r, 2);
return c;
}
}
}
}
int main()
{
// freopen("in.txt", "r", stdin);
// freopen("out.txt", "w", stdout);
int T, N, M, x, y;
char op[5];
scanf("%d", &T);
while (T--)
{
scanf("%d %d", &N, &M);
creat(1, 0, N-1);
for (int i = 0; i < N; ++i)
{
scanf("%d", &seq[i]);
modify(1, i, seq[i]);
}
for (int i = 0; i < M; ++i)
{
scanf("%s %d %d", op, &x, &y);
if (op[0] == 'U')
{
modify(1, x, y);
}
else
{
printf("%d\n", query(1, x, y, 0));
}
}
}
return 0;
}
这时一种改进后的写法,直接query(),详见代码:
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <algorithm>
#define MAXN 100005
#define L(x) ((x)<<1)
#define R(x) ((x)<<1|1)
using namespace std;
int seq[MAXN];
struct
{
int l, r, lmax, rmax, max;
}seg[MAXN*3];
void up(int f)
{
int mid = (seg[f].l+seg[f].r)>>1;
seg[f].lmax = seg[f<<1].lmax;
seg[f].rmax = seg[f<<1|1].rmax;
if (seg[f<<1].lmax == seg[f<<1].r-seg[f<<1].l+1 && seq[mid]<seq[mid+1])
{
seg[f].lmax += seg[f<<1|1].lmax;
}
if (seg[f<<1|1].rmax == seg[f<<1|1].r-seg[f<<1|1].l+1 && seq[mid]<seq[mid+1])
{
seg[f].rmax += seg[f<<1].rmax;
}
seg[f].max = max(seg[f<<1].max, seg[f<<1|1].max);
// 这里写错了,弄了大半天
if (seq[mid]<seq[mid+1])
seg[f].max = max(seg[f].max, seg[f<<1].rmax+seg[f<<1|1].lmax);
}
void build(int f, int l, int r)
{
int mid = (l+r) >> 1;
// 初始化的地方
seg[f].l = l, seg[f].r = r;
if (r > l)
{
build(f<<1, l, mid);
build(f<<1|1, mid+1, r);
up(f);
}
else
seg[f].lmax = seg[f].rmax = seg[f].max = 1;
}
void modify(int f, int pos, int y)
{
int mid = (seg[f].l+seg[f].r)>>1;
if (seg[f].l == seg[f].r)
{
seq[pos] = y;
}
else if (seg[f].r > seg[f].l)
{
if (pos <= mid)
modify(f<<1, pos, y);
else if (pos > mid)
modify(f<<1|1, pos, y);
// 非常重要的维护阶段
up(f);
}
}
int query(int f, int l, int r)
{
int mid = (seg[f].l+seg[f].r)>>1;
if (l == seg[f].l && r == seg[f].r)
{
return seg[f].max;
}
else if (seg[f].r > seg[f].l)
{
if (r <= mid)
query(f<<1, l, r);
else if (l > mid)
query(f<<1|1, l, r);
else
{
int a, b, c, d;
a = max(query(f<<1, l, mid), query(f<<1|1, mid+1, r));
b = min(mid-l+1, seg[f<<1].rmax);
c = min(r-mid, seg[f<<1|1].lmax);
if (seq[mid]<seq[mid+1])
return max(a, b+c);
else
return max(a, max(b, c));
}
}
}
int main()
{
// freopen("in.txt", "r", stdin);
// freopen("out.txt", "w", stdout);
int T, N, M, x, y;
char op[5];
scanf("%d", &T);
while (T--)
{
scanf("%d %d", &N, &M);
for (int i = 0; i < N; ++i)
{
scanf("%d", &seq[i]);
}
build(1, 0, N-1);
for (int i = 0; i < M; ++i)
{
scanf("%s %d %d", op, &x, &y);
if (op[0] == 'U')
{
modify(1, x, y);
}
else
{
printf("%d\n", query(1, x, y));
}
}
}
return 0;
}