您的位置:首页 > 其它

HDU 3308 LCIS(线段树)

2014-10-13 17:21 239 查看


HDU 3308 LCIS

题目链接

题意:一个序列,每次询问一个区间内最长连续上升子序列,或者修改一个位置的值

思路:线段树的区间合并,和最长连续子序列和是一样的思路,记录lsum, rsum, sum,表示左边连续长度,右边连续长度,和区间最长长度,然后pushup的时候进行区间合并操作即可

代码:

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;

#define lson(x) ((x<<1)+1)
#define rson(x) ((x<<1)+2)

const int N = 100005;

int t, n, m, a
;
struct Node {
int l, r, lsum, rsum, sum;
int size() {return r - l + 1;}
} node[N * 4];

void merge(Node &x, Node lson, Node rson) {
x.l = lson.l; x.r = rson.r;
x.lsum = lson.lsum; x.rsum = rson.rsum; x.sum = max(lson.sum, rson.sum);
if (a[lson.r] < a[rson.l]) {
if (lson.lsum == lson.size())
x.lsum = lson.lsum + rson.lsum;
if (rson.rsum == rson.size())
x.rsum = lson.rsum + rson.rsum;
x.sum = max(x.sum, lson.rsum + rson.lsum);
}
}

void pushup(int x) {
merge(node[x], node[lson(x)], node[rson(x)]);
}

void build(int l, int r, int x = 0) {
node[x].l = l; node[x].r = r;
if (l == r) {
node[x].lsum = node[x].rsum = node[x].sum = 1;
return;
}
int mid = (l + r) / 2;
build(l, mid, lson(x));
build(mid + 1, r, rson(x));
pushup(x);
}

void add(int v, int val, int x = 0) {
if (node[x].l == node[x].r) {
a[node[x].l] = val;
return;
}
int mid = (node[x].l + node[x].r) / 2;
if (v <= mid) add(v, val, lson(x));
if (v > mid) add(v, val, rson(x));
pushup(x);
}

Node query(int l, int r, int x = 0) {
if (node[x].l >= l && node[x].r <= r)
return node[x];
int mid = (node[x].l + node[x].r) / 2;
if (l <= mid && r > mid) {
Node tmp;
merge(tmp, query(l, r, lson(x)), query(l, r, rson(x)));
return tmp;
}
else if (l <= mid) return query(l, r, lson(x));
else if (r > mid) return query(l, r, rson(x));
}

int main() {
scanf("%d", &t);
while (t--) {
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; i++)
scanf("%d", &a[i]);
build(1, n);
char op[2];
int x, y;
while (m--) {
scanf("%s%d%d", op, &x, &y);
if (op[0] == 'U') add(x + 1, y);
else printf("%d\n", query(x + 1, y + 1).sum);
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: