AC日记——The Child and Sequence codeforces 250D

D - The Child and Sequence

 

思路:

  因为有区间取模操作所以没法用标记下传;

  我们发现,当一个数小于要取模的值时就可以放弃;

  凭借这个来减少更新线段树的次数;

 

来,上代码:

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

using namespace std;

#define maxn 100005
#define ll long long

struct TreeNodeType {
    ll l, r, mid, dis, max;
};
struct TreeNodeType tree[maxn << 2];

ll n,m;

inline void in(ll &now)
{
    char Cget = getchar(); now = 0;
    while (Cget > '9' || Cget < '0') Cget = getchar();
    while (Cget >= '0'&&Cget <= '9')
    {
        now = now * 10 + Cget - '0';
        Cget = getchar();
    }
}

void tree_build(ll now, ll l, ll r)
{
    tree[now].l = l, tree[now].r = r;
    if (l == r)
    {
        in(tree[now].dis);
        tree[now].max = tree[now].dis;
        return;
    }
    tree[now].mid = l + r >> 1;
    tree_build(now << 1, l, tree[now].mid);
    tree_build(now << 1 | 1, tree[now].mid + 1, r);
    tree[now].dis = tree[now << 1].dis + tree[now << 1 | 1].dis;
    tree[now].max = max(tree[now << 1].max, tree[now << 1 | 1].max);
}

void tree_to(ll now, ll to,ll x)
{
    if (tree[now].l == tree[now].r)
    {
        tree[now].dis = x;
        tree[now].max = x;
        return;
    }
    if (to <= tree[now].mid) tree_to(now << 1, to, x);
    else tree_to(now << 1 | 1, to, x);
    tree[now].dis = tree[now << 1].dis + tree[now << 1 | 1].dis;
    tree[now].max = max(tree[now << 1].max, tree[now << 1 | 1].max);
}

void tree_mod(ll now, ll l, ll r, ll x)
{
    if (tree[now].max < x) return;
    if (tree[now].l >= l&&tree[now].r <= r) tree[now].dis %= x, tree[now].max %= x;
    if (tree[now].l == tree[now].r) return;
    if (l <= tree[now].mid) tree_mod(now << 1, l, r, x);
    if (r > tree[now].mid) tree_mod(now << 1|1, l, r, x);
    tree[now].dis = tree[now << 1].dis + tree[now << 1 | 1].dis;
    tree[now].max = max(tree[now << 1].max, tree[now << 1 | 1].max);
    //cout <<"^ "<< l << ' ' << r << ' ' << tree[now].dis << ' ' << tree[now].max << endl;
}

ll tree_query(ll now, ll l, ll r)
{
    if (tree[now].l == l&&tree[now].r == r) return tree[now].dis;
    if (l > tree[now].mid) return tree_query(now << 1 | 1, l, r);
    else if (r <= tree[now].mid) return tree_query(now << 1, l, r);
    else return tree_query(now << 1, l, tree[now].mid) + tree_query(now << 1 | 1, tree[now].mid + 1, r);
}

int main()
{
    in(n), in(m);
    tree_build(1, 1, n);
    ll op, u, v, x;
    for (; m--;)
    {
        in(op),in(u),in(v);
        if (op == 1) printf("%lld\n", tree_query(1, u, v));
        if (op == 2) in(x), tree_mod(1, u, v, x);
        if (op == 3) tree_to(1, u, v);
    }
    return 0;
}

 

转载于:https://www.cnblogs.com/IUUUUUUUskyyy/p/6800235.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值