HDU 3397 Sequence operation

题意:

有3中操作:

0 a b 从a到b都置为0

1 a b 从a到b都置成1

2 a b 从a到b都进行异或

2中输出:

3 a b 输出从a到b的1的个数

4 a b 输出从a到b连续的1的个数

思路:

这道题可是坑蒙我了,断断续续能写了几个月。

最近才弄明白些,我原先的思路就是记录0和记录1的,然后异或就把1和0的信息进行互换。

后来才发现正解原来是只需要记一个数组f[10000];

0表示全为0

1表示全为1

-1表示混合的

然后开个全局变量记录长度就可以了;

具体看代码

Code:

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cctype>
#include<cmath>
#include<algorithm>
#include<iostream>
#include<string>
#include<vector>
#include<bitset>
#include<queue>
#include<stack>
#include<list>
#include<map>
#include<set>

#define TEST

#define LL long long
#define Mt(f, x) memset(f, x, sizeof(f));
#define rep(i, s, e) for(int i = (s); i <= (e); ++i)
#ifdef TEST
    #define See(a) cout << #a << " = " << a << endl;
    #define See2(a, b) cout << #a << " = " << a << ' ' << #b << " = " << b << endl;
    #define debug(a, s, e) rep(_i, s, e) {cout << a[_i] << ' ';} cout << endl;
    #define debug2(a, s, e, ss, ee) rep(i_, s, e) {debug(a[i_], ss, ee)}
#else
    #define See(a)
    #define See2(a, b)
    #define debug(a, s, e)
    #define debug2(a, s, e, ss, ee)
#endif // TEST

const int MAX = 2e9;
const int MIN = -2e9;
const double eps = 1e-8;
const double PI = acos(-1.0);

using namespace std;

#define lson l, m, rt << 1
#define rson m + 1, r, rt << 1 | 1
#define ls rt << 1
#define rs rt << 1 | 1

const int N = 100000 + 5;

int f[N << 2], lastR, maxLen, temLen;//lastR是刚刚处理过区间的右边,maxLen, temLen是用来记录长度的

void pushUp(int rt)
{
    if(f[ls] == f[rs])
    {
        f[rt] = f[ls];
    }
    else
    {
        f[rt] = -1;
    }
}

void build(int l, int r, int rt)
{
    if(l == r)
    {
        scanf("%d", &f[rt]);
        return ;
    }
    int m = (l + r) >> 1;
    build(lson);
    build(rson);
    pushUp(rt);
}

void pushDown(int rt)
{
    if(f[rt] >= 0)
    {
        f[ls] = f[rs] = f[rt];
        f[rt] = -1;
    }
}

void update(int L, int R, int v, int l, int r, int rt)
{
    if(f[rt] == v)
    {
        return ;
    }
    if(L <= l && r <= R)
    {
        f[rt] = v;
        return;
    }
    pushDown(rt);
    int m = (l + r) >> 1;
    if(L <= m)
        update(L, R, v, lson);
    if(R > m)
        update(L, R, v, rson);
    pushUp(rt);
}

void updateXor(int L, int R, int l, int r, int rt)
{
    if(L <= l && r <= R && f[rt] >= 0)
    {
        f[rt] ^= 1;
        return ;
    }
    pushDown(rt);
    int m = (l + r) >> 1;
    if(L <= m)
        updateXor(L, R, lson);
    if(R > m)
        updateXor(L, R, rson);
    pushUp(rt);
}

int query(int L, int R, int l, int r, int rt)
{
    if(L <= l && r <= R && f[rt] >= 0)
    {
        return f[rt] * (r - l + 1);
    }
    pushDown(rt);
    int m = (l + r) >> 1;
    if(R <= m)
        return query(L, R, lson);
    if(L > m)
        return query(L, R, rson);
    return query(L, R, lson) + query(L, R, rson);
}

void queryL(int L, int R, int l, int r, int rt)
{
    if(f[rt] == 0)
    {
        return ;
    }
    if(L <= l && r <= R && f[rt] == 1)
    {
        if(L == lastR + 1)//判断这个区间是否和上个区间连续
        {
            temLen += r - l + 1;
        }
        else
        {
            temLen = r - l + 1;
        }
        maxLen = max(maxLen, temLen);
        lastR = r;
        return ;
    }
    pushDown(rt);
    int m = (l + r) >> 1;
    if(R <= m)
        queryL(L, R, lson);
    else if(L > m)
        queryL(L, R, rson);
    else
    queryL(L, m, lson) , queryL(m + 1, R, rson);
}

int main()
{
    int T;
    cin >> T;
    while(T--)
    {
        int n, Q;
        scanf("%d%d", &n, &Q);
        build(1, n, 1);
        while(Q--)
        {
            int op, a, b;
            scanf("%d%d%d", &op, &a, &b);
            a++, b++;
            switch(op)
            {
                case 0:
                case 1:
                    update(a, b, op, 1, n, 1);break;
                case 2:
                    updateXor(a, b, 1, n, 1);break;
                case 3:
                    printf("%d\n", query(a, b, 1, n, 1));break;
                case 4:
                    maxLen = 0, temLen = 0;
                    lastR = 0;
                    queryL(a, b, 1, n, 1);
                    printf("%d\n", maxLen);
                    break;
            }
        }
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值