Codeforces Round 921 (Div. 1) B. Space Harbour(线段树,2100)

Problem - 1924B - Codeforces

考虑线段树维护一个区间[l,r]的代价和sum,离l最近的关键点的权值val,区间中每个点到其最右侧关键点的距离和

对于一个点来说,他的权值为 它左侧最近的关键点的权值val * 它到它右侧最近的关键点的距离dis

对于一个不包含关键点的区间[l,r],这个区间的权值为

而假设我们要在这个区间中的某个点x插入一个关键点

那么对于其左边的区间[l,x-1],这个区间的关键点权值val不变,而距离会减去

对于其右侧的区间[x+1,r],这个区间的距离不变,而关键点的权值val会变成val[x]

对于x这个点本身,将他的代价和,权值,距离都更新为0即可

cpp 复制代码
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define lc p << 1
#define rc p << 1 | 1
int n, m, q;
const int N = 3e5 + 5;
int w[N];
set<int> s;
int val[N];
struct node
{
    int l, r;
    int dis, val, sum, lazyval, lazydis;
} tr[N * 4];

void pushup(int p)
{
    tr[p].dis = tr[lc].dis + tr[rc].dis;
    tr[p].sum = tr[lc].sum + tr[rc].sum;
    tr[p].val = tr[lc].val;
}

void pushdown(int p)
{
    if (tr[p].lazyval || tr[p].lazydis)
    {
        if (tr[p].lazyval)
        {
            tr[lc].val = tr[p].lazyval;
            tr[rc].val = tr[p].lazyval;
            tr[lc].lazyval = tr[p].lazyval;
            tr[rc].lazyval = tr[p].lazyval;
            tr[p].lazyval = 0;
        }
        if (tr[p].lazydis)
        {
            tr[lc].dis -= (tr[lc].r - tr[lc].l + 1) * tr[p].lazydis;
            tr[rc].dis -= (tr[rc].r - tr[rc].l + 1) * tr[p].lazydis;
            tr[lc].lazydis += tr[p].lazydis;
            tr[rc].lazydis += tr[p].lazydis;
            tr[p].lazydis = 0;
        }
        tr[lc].sum = tr[lc].val * tr[lc].dis;
        tr[rc].sum = tr[rc].val * tr[rc].dis;
    }
}

void build(int p, int l, int r)
{
    tr[p] = {l, r, 0, 0, 0, 0, 0};
    if (l == r)
    {
        auto nex = s.lower_bound(l);
        if (*nex == l)
            return;
        auto pre = nex;
        pre--;
        tr[p].val = val[*pre];
        tr[p].dis = *nex - l;
        tr[p].sum = tr[p].val * tr[p].dis;
        return;
    }
    int mid = l + r >> 1;
    build(lc, l, mid);
    build(rc, mid + 1, r);
    pushup(p);
}
void updateval(int p, int x, int y, int k)
{
    if (tr[p].l >= x && tr[p].r <= y)
    {
        tr[p].val = k;
        tr[p].lazyval = k;
        tr[p].sum = tr[p].dis * tr[p].val;
        return;
    }
    int mid = tr[p].l + tr[p].r >> 1;
    pushdown(p);
    if (mid >= x)
        updateval(lc, x, y, k);
    if (mid < y)
        updateval(rc, x, y, k);
    pushup(p);
}
void updatedis(int p, int x, int y, int k)
{
    if (tr[p].l >= x && tr[p].r <= y)
    {
        tr[p].lazydis += k;
        tr[p].dis -= k * (tr[p].r - tr[p].l + 1);
        tr[p].sum = tr[p].dis * tr[p].val;
        return;
    }
    int mid = tr[p].l + tr[p].r >> 1;
    pushdown(p);
    if (mid >= x)
        updatedis(lc, x, y, k);
    if (mid < y)
        updatedis(rc, x, y, k);
    pushup(p);
}
void update(int p, int x)
{
    if (tr[p].l == tr[p].r && tr[p].l == x)
    {
        tr[p] = {x, x, 0, 0, 0, 0, 0};
        return;
    }
    int mid = tr[p].l + tr[p].r >> 1;
    pushdown(p);
    if (mid >= x)
        update(lc, x);
    else
        update(rc, x);
    pushup(p);
}
int query(int p, int x, int y)
{
    if (tr[p].l >= x && tr[p].r <= y)
    {
        return tr[p].sum;
    }
    int mid = tr[p].l + tr[p].r >> 1;
    int sum = 0;
    pushdown(p);
    if (mid >= x)
        sum += query(lc, x, y);
    if (mid < y)
        sum += query(rc, x, y);
    pushup(p);
    return sum;
}

signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    cin >> n >> m >> q;
    vector<int> X(m + 1);
    for (int i = 1; i <= m; i++)
        cin >> X[i], s.insert(X[i]);
    for (int i = 1; i <= m; i++)
        cin >> val[X[i]];
    build(1, 1, n);
    while (q--)
    {
        int opt;
        cin >> opt;
        if (opt == 1)
        {
            int x, v;
            cin >> x >> v;
            val[x] = v;
            s.insert(x);
            auto it = s.find(x);
            auto pre = it, nex = it;
            pre--, nex++;
            int pe = *pre, nx = *nex;
            if (x - 1 >= pe + 1)
                updatedis(1, pe + 1, x - 1, nx - x);
            if (nx - 1 >= x + 1)
                updateval(1, x + 1, nx - 1, v);
            update(1, x);
        }
        else
        {
            int l, r;
            cin >> l >> r;
            cout << query(1, l, r) << endl;
        }
    }
}
相关推荐
Mr_Xuhhh36 分钟前
Qt窗口(2)-工具栏
java·c语言·开发语言·数据库·c++·qt·算法
JQLvopkk1 小时前
C#通过HslCommunication连接西门子PLC1200,并防止数据跳动的通用方法
前端·javascript·算法
艾莉丝努力练剑1 小时前
【数据结构与算法】数据结构初阶:详解顺序表和链表(五)——双向链表
c语言·开发语言·数据结构·学习·算法
李昊哲小课1 小时前
支持向量机SVM
人工智能·算法·机器学习·支持向量机·数据挖掘·sklearn
jndingxin1 小时前
OpenCV多尺度图像增强算法函数BIMEF()
人工智能·opencv·算法
算法_小学生1 小时前
Hinge Loss(铰链损失函数)详解:SVM 中的关键损失函数
开发语言·人工智能·python·算法·机器学习·支持向量机
paopaokaka_luck2 小时前
基于SpringBoot+Vue的汽车租赁系统(协同过滤算法、腾讯地图API、支付宝沙盒支付、WebsSocket实时聊天、ECharts图形化分析)
vue.js·spring boot·后端·websocket·算法·汽车·echarts
kyle~2 小时前
C++---cout、cerr、clog
开发语言·c++·算法
钢铁男儿2 小时前
PyQt5信号与槽(信号与槽的高级玩法)
python·qt·算法
Aurora_wmroy4 小时前
算法竞赛备赛——【图论】求最短路径——Floyd算法
数据结构·c++·算法·蓝桥杯·图论