hdu 3397 Sequence operation (线段树+区间合并+双Lazy标记)

给你一个长度为n的0、1序列,然后对该序列进行m次操作(1<=n, m<=100000)。操作共有5种:

0 a b 将[a, b]上的所有数变为0;

1 a b 将[a, b]上的所有数变为1;

2 a b 将[a, b]上的0变成1,1变成0;

3 a b 输出[a, b]上1的个数;

4 a b 输出[a, b]上最长的连续的1的数目。


刚开始做的时候就想用两个Lazy标记,一个覆盖标记,一个异或标记。但敲的过程中发现两个标记很难处理,于是就去掉了异或标记。敲好调试好交了两次后1015msAC。但我觉得如果用双标记的话应该会更快,于是又重新敲了个双标记的。结果1140msAC,竟然比单标记的还慢了100+ms。想了想,应该是传递异或标记时花了太多的时间吧~~

把两个代码都贴一下:


“覆盖”标记

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>

using namespace std;

const int maxn = 111111;
int sum[maxn<<2], llen1[maxn<<2], rlen1[maxn<<2], mlen1[maxn<<2];
int cov[maxn<<2];

void f_cov(int c, int l, int r, int rt)
{
    cov[rt] = c;
    sum[rt] = llen1[rt] = rlen1[rt] = mlen1[rt] = c ? r - l + 1 : 0;
}

void pushUp(int l, int r, int rt)
{
    int m = (l + r) >> 1;
    sum[rt] = sum[rt<<1] + sum[rt<<1|1];
    llen1[rt] = llen1[rt<<1];
    rlen1[rt] = rlen1[rt<<1|1];
    if (llen1[rt] == m - l + 1)
        llen1[rt] += llen1[rt<<1|1];
    if (rlen1[rt] == r - m)
        rlen1[rt] += rlen1[rt<<1];
    mlen1[rt] = max(rlen1[rt<<1] + llen1[rt<<1|1], max(mlen1[rt<<1], mlen1[rt<<1|1]));
}

void pushDown(int l, int r, int rt)
{
    if (cov[rt] != -1)
    {
        int m = (l + r) >> 1;
        f_cov(cov[rt], l, m, rt << 1);
        f_cov(cov[rt], m + 1, r, rt << 1 | 1);
        cov[rt] = -1;
    }
}

void build(int l, int r, int rt)
{
    cov[rt] = -1;
    if (l == r)
    {
        scanf("%d", &sum[rt]);
        cov[rt] = llen1[rt] = rlen1[rt] = mlen1[rt] = sum[rt];
        return ;
    }
    int m = (l + r) >> 1;
    build(l, m, rt << 1);
    build(m + 1, r, rt << 1 | 1);
    pushUp(l, r, rt);
}

void update_change(int L, int R, int c, int l, int r, int rt)
{
    if (L <= l && R >= r)
    {
        f_cov(c, l, r, rt);
        return ;
    }
    pushDown(l, r, rt);
    int m = (l + r) >> 1;
    if (L <= m) update_change(L, R, c, l, m, rt << 1);
    if (R > m) update_change(L, R, c, m + 1, r, rt << 1 | 1);
    pushUp(l, r, rt);
}

void update_xor(int L, int R, int l, int r, int rt)
{
    if (L <= l && R >= r)
    {
        if (cov[rt] != -1)
        {
            cov[rt] ^= 1;
            sum[rt] = llen1[rt] = rlen1[rt] = mlen1[rt] = cov[rt] ? r - l + 1 : 0;
            return ;
        }
    }
    pushDown(l, r, rt);
    int m = (l + r) >> 1;
    if (L <= m) update_xor(L, R, l, m, rt << 1);
    if (R > m) update_xor(L, R, m + 1, r, rt << 1 | 1);
    pushUp(l, r, rt);
}

int query_sum(int L, int R, int l, int r, int rt)
{
    if (L <= l && R >= r)
        return sum[rt];
    pushDown(l, r, rt);
    int m = (l + r) >> 1;
    int ret = 0;
    if (L <= m) ret += query_sum(L, R, l, m, rt << 1);
    if (R > m) ret += query_sum(L, R, m + 1, r, rt << 1 | 1);
    return ret;
}

int query_len(int L, int R, int l, int r, int rt)
{
    if (L == l && R == r)
        return mlen1[rt];
    pushDown(l, r, rt);
    int m = (l + r) >> 1;
    if (R <= m) return query_len(L, R, l, m, rt << 1);
    else if (L > m) return query_len(L, R, m + 1, r, rt << 1 | 1);
    else
    {
        int a = query_len(L, m, l, m, rt << 1);
        int b = query_len(m + 1, R, m + 1, r, rt << 1 | 1);
        int c = 0;
        c += min(rlen1[rt<<1], m - L + 1);
        c += min(llen1[rt<<1|1], R - m);

        return max(a, max(b, c));
    }
}

int main()
{
    int t, n, m;
    int op, a, b;
    scanf("%d", &t);
    while (t--)
    {
        scanf("%d %d", &n, &m);
        build(0, n - 1, 1);
        while (m--)
        {
            scanf("%d %d %d", &op, &a, &b);
            if (op == 0 || op == 1)
                update_change(a, b, op, 0, n - 1, 1);
            else if(op == 2)
                update_xor(a, b, 0, n - 1, 1);
            else if (op == 3)
                printf("%d\n", query_sum(a, b, 0, n - 1, 1));
            else printf("%d\n", query_len(a, b, 0, n - 1, 1));
        }
    }
    return 0;
}


“覆盖”和“异或”双标记

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>

using namespace std;

const int maxn = 111111;
int sum[maxn<<2], cov[maxn<<2], XOR[maxn<<2];
int llen1[maxn<<2], rlen1[maxn<<2], mlen1[maxn<<2];
int llen0[maxn<<2], rlen0[maxn<<2], mlen0[maxn<<2];

void f_cov(int c, int l, int r, int rt) // 覆盖操作
{
    cov[rt] = c;
    XOR[rt] = 0; // 覆盖时,异或标记直接清零
    sum[rt] = c ? r - l + 1 : 0;
    llen0[rt] = rlen0[rt] = mlen0[rt] = c ? 0 : r - l + 1;
    llen1[rt] = rlen1[rt] = mlen1[rt] = c ? r - l + 1 : 0;
}

void f_xor(int l, int r, int rt) // 异或操作
{
    if (cov[rt] != -1) cov[rt] ^= 1;
    else XOR[rt] ^= 1;
    sum[rt] = (r - l + 1) - sum[rt];
    swap(llen0[rt], llen1[rt]);
    swap(rlen0[rt], rlen1[rt]);
    swap(mlen0[rt], mlen1[rt]);
}

void pushUp(int l, int r, int rt)
{
    int m = (l + r) >> 1;
    sum[rt] = sum[rt<<1] + sum[rt<<1|1];

    llen1[rt] = llen1[rt<<1];
    rlen1[rt] = rlen1[rt<<1|1];
    if (llen1[rt] == m - l + 1)
        llen1[rt] += llen1[rt<<1|1];
    if (rlen1[rt] == r - m)
        rlen1[rt] += rlen1[rt<<1];
    mlen1[rt] = max(rlen1[rt<<1] + llen1[rt<<1|1], max(mlen1[rt<<1], mlen1[rt<<1|1]));

    llen0[rt] = llen0[rt<<1];
    rlen0[rt] = rlen0[rt<<1|1];
    if (llen0[rt] == m - l + 1)
        llen0[rt] += llen0[rt<<1|1];
    if (rlen0[rt] == r - m)
        rlen0[rt] += rlen0[rt<<1];
    mlen0[rt] = max(rlen0[rt<<1] + llen0[rt<<1|1], max(mlen0[rt<<1], mlen0[rt<<1|1]));
}

void pushDown(int l, int r, int rt)
{
    int m = (l + r) >> 1;
    if (cov[rt] != -1)
    {
        f_cov(cov[rt], l, m, rt << 1);
        f_cov(cov[rt], m + 1, r, rt << 1 | 1);
        cov[rt] = -1;
    }
    if (XOR[rt])
    {
        f_xor(l, m, rt << 1);
        f_xor(m + 1, r, rt << 1 | 1);
        XOR[rt] = 0;
    }
}

void build(int l, int r, int rt)
{
    cov[rt] = -1;
    XOR[rt] = 0;
    if (l == r)
    {
        scanf("%d", &sum[rt]);
        cov[rt] = llen1[rt] = rlen1[rt] = mlen1[rt] = sum[rt];
        llen0[rt] = rlen0[rt] = mlen0[rt] = 1 - sum[rt];
        return ;
    }
    int m = (l + r) >> 1;
    build(l, m, rt << 1);
    build(m + 1, r, rt << 1 | 1);
    pushUp(l, r, rt);
}

void update(int L, int R, int c, int l, int r, int rt)
{
    if (L <= l && R >= r)
    {
        if (c == 0 || c == 1)
            f_cov(c, l, r, rt);
        if (c == 2)
            f_xor(l, r, rt);
        return ;
    }
    pushDown(l, r, rt);
    int m = (l + r) >> 1;
    if (L <= m) update(L, R, c, l, m, rt << 1);
    if (R > m) update(L, R, c, m + 1, r, rt << 1 | 1);
    pushUp(l, r, rt);
}

int query_sum(int L, int R, int l, int r, int rt)
{
    if (L <= l && R >= r)
        return sum[rt];
    pushDown(l, r, rt);
    int m = (l + r) >> 1;
    int ret = 0;
    if (L <= m) ret += query_sum(L, R, l, m, rt << 1);
    if (R > m) ret += query_sum(L, R, m + 1, r, rt << 1 | 1);
    return ret;
}

int query_len(int L, int R, int l, int r, int rt)
{
    if (L == l && R == r)
        return mlen1[rt];
    pushDown(l, r, rt);
    int m = (l + r) >> 1;
    if (R <= m) return query_len(L, R, l, m, rt << 1);
    else if (L > m) return query_len(L, R, m + 1, r, rt << 1 | 1);
    else
    {
        int a = query_len(L, m, l, m, rt << 1);
        int b = query_len(m + 1, R, m + 1, r, rt << 1 | 1);
        int c = 0;
        c += min(rlen1[rt<<1], m - L + 1);
        c += min(llen1[rt<<1|1], R - m);

        return max(a, max(b, c));
    }
}

int main()
{
    int t, n, m;
    int op, a, b;
    scanf("%d", &t);
    while (t--)
    {
        scanf("%d %d", &n, &m);
        build(0, n - 1, 1);
        while (m--)
        {
            scanf("%d %d %d", &op, &a, &b);
            if (op <= 2)
                update(a, b, op, 0, n - 1, 1);
            else if (op == 3)
                printf("%d\n", query_sum(a, b, 0, n - 1, 1));
            else printf("%d\n", query_len(a, b, 0, n - 1, 1));
        }
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值