惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

人人都是产品经理
人人都是产品经理
MyScale Blog
MyScale Blog
Y
Y Combinator Blog
罗磊的独立博客
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
P
Proofpoint News Feed
Google DeepMind News
Google DeepMind News
V
Vulnerabilities – Threatpost
T
The Blog of Author Tim Ferriss
云风的 BLOG
云风的 BLOG
Recorded Future
Recorded Future
N
News and Events Feed by Topic
B
Blog RSS Feed
阮一峰的网络日志
阮一峰的网络日志
博客园_首页
C
CXSECURITY Database RSS Feed - CXSecurity.com
博客园 - 【当耐特】
N
Netflix TechBlog - Medium
博客园 - 叶小钗
B
Blog
Vercel News
Vercel News
T
Tenable Blog
T
The Exploit Database - CXSecurity.com
Spread Privacy
Spread Privacy
T
Threat Research - Cisco Blogs
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
Last Week in AI
Last Week in AI
F
Fortinet All Blogs
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
Microsoft Security Blog
Microsoft Security Blog
S
Securelist
Microsoft Azure Blog
Microsoft Azure Blog
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
P
Palo Alto Networks Blog
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
D
DataBreaches.Net
Cyberwarzone
Cyberwarzone
Engineering at Meta
Engineering at Meta
Martin Fowler
Martin Fowler
G
GRAHAM CLULEY
Project Zero
Project Zero
Cisco Talos Blog
Cisco Talos Blog
A
Arctic Wolf
C
CERT Recently Published Vulnerability Notes
L
LangChain Blog
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
C
Check Point Blog
A
About on SuperTechFans
W
WeLiveSecurity
The GitHub Blog
The GitHub Blog

博客园 - 糖豆爸爸

【树上DP前导知识汇总】 快速幂、龟速乘总结 反向建图+拓扑排序 卡特兰数专题(Catalan) AcWing 126. 最大的和 AcWing 431. 守望者的逃离 AcWing 414. 数字游戏 AcWing 468. 魔法阵 AcWing 463. 求和 洛谷 P1632 点的移动 P1056 NOIP2008 普及组 排座椅 洛谷 P1889 士兵站队 洛谷 P1862 输油管道问题 P2253 好一个一中腰鼓! SCOI2010 P2572 序列操作 P4344 SHOI2015 脑洞治疗仪 T125847 【模板】动态开点线段树 P3373 【模板】线段树 2 Physical Education Lessons
CF444C DZY Loves Colors
糖豆爸爸 · 2023-09-06 · via 博客园 - 糖豆爸爸

\(DZY\) \(Loves\) \(Colors\)

一、题面翻译

有一个 \(n\) 个元素组成的序列,每个元素有两个属性:颜色 \(c_i\) 和权值\(w_i\)\(c_i\) 初始为\(i\)\(w_i\)初始为 \(0\)

\(m\) 次操作,操作有两种:

  • 1 l r x:对\(i \in [l,r]\) 的所有 \(i\) 进行如下操作:设第 \(i\) 个元素 原来 的颜色为 \(y\),您要把第 \(i\) 个元素的颜色改为 \(x\),权值 增加 \(|y-x|\)

  • 2 l r:求 \(\displaystyle \sum_{i=l}^rw_i\)

  • \(1 \le n,m \le 10^5,1 \le x \le 10^8\)

二、题目解析

  • ① 修改涉及到绝对值,可以通过判断区间内的数是否全部相等再进行区间操作,区间内的数是否全部相等用属性标签\(same\)表示
  • ② 通过懒标记 \(same\) 判断该区间的所有颜色是否都相等,相等时就可以将懒标记下传,更新\(add\)
  • ③ 递归出口:递归到叶子时,叶子一定满足\(tr[u].same=color[i]>0\),每次我们修改时候对相同的颜色段修改,不相同的颜色段递归暴力修改
  • ④ 本题不是一道标准的懒标记题目,而是一个类似于魔改的懒标记题目:根据区间上的属性决定是否在区间上进行统计、打懒标记标签,如果不符合,就递归到叶子,暴力统计

三、实现代码

#include <bits/stdc++.h>
using namespace std;

const int N = 500010;

#define int long long
#define mid ((l + r) >> 1)
#define ls (u << 1)
#define rs (u << 1 | 1)
struct Node {
    int l, r, len;
    int sum;  // 属性:权值的和 sum(Wi)
    int same; // 属性:区间的颜色值是否相同,如果相同,记录颜色值为same,注意:颜色值从1开始,最大是n
    int add;  // 懒标记:增加
} tr[N << 2];

void pushup(int u) {
    tr[u].sum = tr[ls].sum + tr[rs].sum; // 属性1:Wi权值和
    if (tr[ls].same == tr[rs].same)      // 属性2:same属性。如果左右儿子的same属性一致,则父亲的same属性标注为左儿子的same属性
        tr[u].same = tr[ls].same;
    else
        tr[u].same = 0;
    // 注意:这个else中的same属性也一定要清零!原来是左右儿子一致,再次修改后就不一致,那么父亲需要标记不一致
    // 这个和初始值为0没有任何关系,最初我还以为不需要加上这句,后来想想不对,这是一个动态变化的过程,需要及时清零
}

void pushdown(int u) {
    if (tr[u].same) { // 如果存在add懒标记,并且整个区间是一样的值
        tr[ls].sum += tr[ls].len * tr[u].add;
        tr[rs].sum += tr[rs].len * tr[u].add;
        tr[ls].add += tr[u].add;
        tr[rs].add += tr[u].add;
        tr[ls].same = tr[u].same;
        tr[rs].same = tr[u].same;
        tr[u].add = 0;
    }
}

void build(int u, int l, int r) {
    tr[u].l = l, tr[u].r = r, tr[u].len = r - l + 1;
    if (l == r) {
        tr[u].same = l; // 颜色值Ci,初始值为i,对于叶子而言i即是l
        return;
    }
    build(ls, l, mid), build(rs, mid + 1, r);
    pushup(u);
}

void modify(int u, int L, int R, int v) {
    int l = tr[u].l, r = tr[u].r;
    if (l > R || r < L) return;

    if (l >= L && r <= R && tr[u].same) {
        tr[u].sum += tr[u].len * abs(v - tr[u].same);
        tr[u].add += abs(v - tr[u].same);
        tr[u].same = v;
        return;
    }
    pushdown(u);
    modify(ls, L, R, v), modify(rs, L, R, v);
    pushup(u);
}

int query(int u, int L, int R) {
    int l = tr[u].l, r = tr[u].r;
    if (l >= L && r <= R) return tr[u].sum;
    if (l > R || r < L) return 0;

    pushdown(u);
    return query(ls, L, R) + query(rs, L, R);
}

signed main() {
#ifndef ONLINE_JUDGE
    freopen("CF444C.in", "r", stdin);
#endif
    // 加快读入
    ios::sync_with_stdio(false), cin.tie(0);
    int n, m, op;
    cin >> n >> m;

    // n个元素,构建线段树
    build(1, 1, n);

    while (m--) {
        int op;
        cin >> op;
        if (op == 1) {
            int l, r, x;
            cin >> l >> r >> x;
            modify(1, l, r, x); // 区间修改为x
        } else if (op == 2) {
            int l, r;
            cin >> l >> r;
            cout << query(1, l, r) << endl;
        }
    }
    return 0;
}