UESTC 1425 Another LCIS

UESTC_1425

    更多和区间合并相关的线段树问题可以参考胡浩的博客:http://www.notonlysuccess.com/index.php/segment-tree-complete/

    这个题和HDU_3308很像,只不过要多处理一下区间加和的操作,为了能够方便的修改、获取左区间的右端点和右区间左端点的大小关系,可以用两个标记lx[]、rx[]分别表示当前区间左端点以及右端点的值。

#include<stdio.h>

#include<string.h>

#define MAXD 100010

int N, Q, a[MAXD], lc[4 * MAXD], rc[4 * MAXD], lx[4 * MAXD], rx[4 * MAXD], mc[4 * MAXD], add[4 * MAXD];

int getmax(int x, int y)

{

    return x > y ? x : y;

}

void update(int cur, int x, int y)

{

    int mid = (x + y) >> 1, ls = cur << 1, rs = (cur << 1) | 1;

    mc[cur] = getmax(mc[ls], mc[rs]);

    lc[cur] = lc[ls], rc[cur] = rc[rs];

    if(rx[ls] < lx[rs])

    {

        if(rc[ls] + lc[rs] > mc[cur])

            mc[cur] = rc[ls] + lc[rs];

        if(lc[ls] == mid - x + 1)

            lc[cur] += lc[rs];

        if(rc[rs] == y - mid)

            rc[cur] += rc[ls];

    }

    lx[cur] = lx[ls], rx[cur] = rx[rs];

}

void pushdown(int cur)

{

    int ls = cur << 1, rs = (cur << 1) | 1;

    if(add[cur])

    {

        add[ls] += add[cur], add[rs] += add[cur];

        lx[ls] += add[cur], rx[ls] += add[cur];

        lx[rs] += add[cur], rx[rs] += add[cur];

        add[cur] = 0;

    }

}

void build(int cur, int x, int y)

{

    int mid = (x + y) >> 1, ls = cur << 1, rs = (cur << 1) | 1;

    add[cur] = 0;

    if(x == y)

    {

        mc[cur] = lc[cur] = rc[cur] = 1;

        lx[cur] = rx[cur] = a[x];

        return ;

    }

    build(ls, x, mid);

    build(rs, mid + 1, y);

    update(cur, x, y);

}

void init()

{

    int i, j, k;

    scanf("%d%d", &N, &Q);

    for(i = 1; i <= N; i ++)

        scanf("%d", &a[i]);

    build(1, 1, N);

}

int query(int cur, int x, int y, int s, int t, int fa, int &ans)

{

    int mid = (x + y) >> 1, ls = cur << 1, rs = (cur << 1) | 1;

    if(x >= s && y <= t)

    {

        if(mc[cur] > ans)

            ans = mc[cur];

        return fa == -1 ? lc[cur] : rc[cur];

    }

    pushdown(cur);

    if(mid >= t)

        return query(ls, x, mid, s, t, -1, ans);

    else if(mid + 1 <= s)

        return query(rs, mid + 1, y, s, t, 1, ans);

    else

    {

        int ln = query(ls, x, mid, s, t, 1, ans), rn = query(rs, mid + 1, y, s, t, -1, ans);

        if(rx[ls] < lx[rs])

        {

            if(ln + rn > ans)

                ans = ln + rn;

            if(fa == -1)

                return lc[ls] == mid - x + 1 ? lc[ls] + rn : lc[ls];

            else

                return rc[rs] == y - mid ? rc[rs] + ln : rc[rs];

        }

        return fa == -1 ? lc[ls] : rc[rs];

    }

}

void refresh(int cur, int x, int y, int s, int t, int v)

{

    int mid = (x + y) >> 1, ls = cur << 1, rs = (cur << 1) | 1;

    if(x >= s && y <= t)

    {

        add[cur] += v, lx[cur] += v, rx[cur] += v;

        return ;

    }

    pushdown(cur);

    if(mid >= s)

        refresh(ls, x, mid, s, t, v);

    if(mid + 1 <= t)

        refresh(rs, mid + 1, y, s, t, v);

    update(cur, x, y);

}

void solve()

{

    int i, j, k, x, y, z, ans;

    char b[5];

    for(i = 0; i < Q; i ++)

    {

        scanf("%s", b);

        if(b[0] == 'q')

        {

            scanf("%d%d", &x, &y);

            ans = 0;

            query(1, 1, N, x, y, -1, ans);

            printf("%d\n", ans);

        }

        else

        {

            scanf("%d%d%d", &x, &y, &z);

            refresh(1, 1, N, x, y, z);

        }

    }

}

int main()

{

    int t, tt;

    scanf("%d", &t);

    for(tt = 0; tt < t; tt ++)

    {

        init();

        printf("Case #%d:\n", tt + 1);

        solve();

    }

    return 0;

}

你可能感兴趣的:(CI)