炸鸡块君与FIFA22 线段树 (2022牛客寒假集训营1)

在这里插入图片描述
在这里插入图片描述
维护三棵线段树,当前%3余数是多少时的得分,进行push_up的时候,右区间对区间的贡献的影响需要加上左区间的影响。具体看代码,清晰易懂

#include <bits/stdc++.h>
#define endl '\n'
#define go continue
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define fory(i,a,b) for(int i = a; i <= b; ++i)
//-----
#define int long long
//-----
using namespace std;

template <typename T> inline void read(T& t)
{
    int f = 0, c = getchar();
    t = 0;
    while (!isdigit(c)) f |= c == '-', c = getchar();
    while (isdigit(c)) t = t * 10 + c - 48, c = getchar();
    if (f) t = -t;
}

template <typename T> void print(T x)
{
    if (x < 0) x = -x, putchar('-');
    if (x > 9) print(x / 10);
    putchar(x % 10 + 48);
}

inline void _sort(int* a, int l, int id)
{
    id == 1 ? sort(a + 1, a + 1 + l, less<int>()) : sort(a + 1, a + 1 + l, greater<int>());
}
//--------------------------------------------
const int N = 2e5 + 10;

int n, m;
char s[N];
int x, y, z;

struct node
{
    int l, r;
    int c[3];
};

struct segment_tree
{
    node t[N << 2];

    inline void push_up(int root)
    {
        int ch = root << 1;
        for(int i = 0; i < 3; ++i)
        {
            t[root].c[i] = t[ch].c[i] + t[ch + 1].c[(i + t[ch].c[i]) % 3];
        }
    }

    inline void build(int root, int l, int r)
    {
        t[root].l = l;
        t[root].r = r;
        if(l != r)
        {
            int mid = (l + r) >> 1;
            int ch = root << 1;
            build(ch, l, mid);
            build(ch + 1, mid + 1, r);
            push_up(root);
        }
        else
        {
            if(s[l] == 'W')
            {
                t[root].c[0] = t[root].c[1] = t[root].c[2] = 1;
            }
            else if(s[l] == 'L')
            {
                t[root].c[0] = 0, t[root].c[1] = t[root].c[2] = -1;
            }
            else
            {
                t[root].c[0] = t[root].c[1] = t[root].c[2] = 0;
            }
        }
    }

    inline node query(int root, int l, int r)
    {
        if(t[root].l >= l && t[root].r <= r)
        {
            return t[root];
        }

        // cout<<"debug"<<endl;

        int mid = (t[root].l + t[root].r) >> 1;
        int ch = root << 1;

        if(r <= mid) return query(ch, l, r);
        else if(l > mid) return query(ch + 1, l, r);
        else
        {
            node left = query(ch, l, mid);
            node right = query(ch + 1, mid + 1, r);
            node res;
            for(int i = 0; i < 3; ++i)
            {
                res.c[i] = left.c[i] + right.c[(i + left.c[i]) % 3];
            }
            return res;
        }
    }

};
segment_tree st;

signed main()
{
    read(n), read(m);
    scanf("%s", s + 1);

    st.build(1, 1, n);

    while(m--)
    {
        read(x), read(y), read(z);
        printf("%lld\n", st.query(1, x, y).c[z % 3] + z);
    }

    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值