• D-温暖的签到题


    链接:https://ac.nowcoder.com/acm/contest/892/D

    题意:

    给你一个长度为n的序列,初始为1,2,3...n,对其进行m次操作。
    操作有两种:
    1 l r  表示将区间[l,r]用 [1,2...r-l+1] 覆盖
    2 l r 查询[l,r]的区间和

    思路:

    线段树

    比赛时思路对的,但是代码写的太乱,没改出来,赛后重写。

    Lazy我开二维数组,记录子节点左右对应的范围。

    其他的就根普通线段树一样。

    代码:

    #include <bits/stdc++.h>
    using namespace std;
     
    typedef long long LL;
    const int MAXN = 1e5+10;
     
    LL Seg[MAXN*4];
    LL Lazy[MAXN*4][2];
    int n, m;
     
    void PushUp(int root)
    {
        Seg[root] = Seg[root<<1]+Seg[root<<1|1];
    }
     
    void PushDown(int root)
    {
        if (Lazy[root][1] != 0)
        {
            LL lenl = Lazy[root][0];
            LL lenr = Lazy[root][1];
            LL lenmid = (lenl+lenr)/2;
            Seg[root<<1] = (lenl+lenmid)*(lenmid-lenl+1)/2;
            Seg[root<<1|1] = (lenmid+1+lenr)*(lenr-lenmid)/2;
            Lazy[root<<1][0] = lenl;
            Lazy[root<<1][1] = lenmid;
            Lazy[root<<1|1][0] = lenmid+1;
            Lazy[root<<1|1][1] = lenr;
            Lazy[root][0] = Lazy[root][1] = 0;
        }
    }
     
    void Build(int root, int l, int r)
    {
        if (l == r)
        {
            Seg[root] = l;
            return;
        }
        int mid = (l+r)/2;
        Build(root<<1, l, mid);
        Build(root<<1|1, mid+1, r);
        PushUp(root);
    }
     
    void Update(int root, int l, int r, int ql, int qr)
    {
        if (r < ql || qr < l)
            return;
        if (ql <= l && r <= qr)
        {
            LL lenl = l-ql+1, lenr = r-ql+1;
            Seg[root] = (lenl+lenr)*(r-l+1)/2;
            Lazy[root][0] = lenl;
            Lazy[root][1] = lenr;
            return;
        }
        PushDown(root);
        int mid = (l+r)/2;
        Update(root<<1, l, mid, ql, qr);
        Update(root<<1|1, mid+1, r, ql, qr);
        PushUp(root);
    }
     
    LL Query(int root, int l, int r, int ql, int qr)
    {
        if (r < ql || qr < l)
            return 0LL;
        if (ql <= l && r <= qr)
            return Seg[root];
        PushDown(root);
        LL res = 0;
        int mid = (l+r)/2;
        res += Query(root<<1, l, mid, ql, qr);
        res += Query(root<<1|1, mid+1, r, ql, qr);
        return res;
    }
     
    int main()
    {
        int op, l, r;
        cin >> n >> m;
        Build(1, 1, n);
        while (m--)
        {
            cin >> op >> l >> r;
            if (op == 1)
                Update(1, 1, n, l, r);
            else
                cout << Query(1, 1, n, l, r) << endl;
        }
     
        return 0;
    }
    

      

  • 相关阅读:
    终端I/O之行控制函数
    终端I/O之波特率函数
    终端I/O之stty命令
    终端I/O之终端选项标志
    终端I/O之获得和设置终端属性
    终端I/O之特殊输入字符
    终端I/O之综述
    css大小单位px em rem的转换和详解
    简单jquery实现select三级联动
    html 页面内锚点定位及跳转方法总结
  • 原文地址:https://www.cnblogs.com/YDDDD/p/10851279.html
Copyright © 2020-2023  润新知