云计算百科
云计算领域专业知识百科平台

打卡信奥刷题(3664)用C++实现信奥题 P12194 [NOISG 2025 Prelim] Snacks

P12194 [NOISG 2025 Prelim] Snacks

题目描述

Shor 小鸭已经准备了 nnn 个小吃盘子,准备一边看电影一边享用!第 iii 个盘子最初装有一个美味值为 a[i]a[i]a[i] 的小吃。

你需要处理 qqq 个查询。在第 jjj 个查询中,Shor 将按顺序执行以下两个操作:

  • 吃掉所有美味值在 l[j]l[j]l[j] 到 r[j]r[j]r[j](包含)之间的小吃。
  • 然后,将每一个被吃掉的小吃替换为一个美味值为 x[j]x[j]x[j] 的新小吃。
  • 在处理任何查询之前,以及每次处理完查询之后,Shor 都希望你确定所有盘子中小吃的美味值总和。

    形式化地说,给定一个长度为 nnn 的数组 aaa,你必须处理 qqq 个查询。在处理所有查询之前,打印 aaa 中所有元素的总和。在第 jjj 个查询中,将所有满足 l[j]≤a[i]≤r[j]l[j] \\leq a[i] \\leq r[j]l[j]≤a[i]≤r[j] 的元素 a[i]a[i]a[i] 更新为 x[j]x[j]x[j],然后打印更新后的 aaa 中所有元素的总和。

    输入格式

    你的程序必须从标准输入读取数据。

    输入的第一行包含两个用空格分隔的整数 nnn 和 qqq。

    第二行包含 nnn 个用空格分隔的整数 a[1],a[2],…,a[n]a[1], a[2], \\ldots, a[n]a[1],a[2],…,a[n]。

    接下来的 qqq 行输入中,每一行包含三个用空格分隔的整数。第 jjj 行包含 l[j],r[j]l[j], r[j]l[j],r[j] 和 x[j]x[j]x[j],描述了第 jjj 个查询。

    输出格式

    你的程序必须将结果打印到标准输出。

    输出应包含 q+1q + 1q+1 行。

    输出的第一行应包含一个整数,表示在所有查询之前 aaa 中所有元素的总和。

    接下来的 qqq 行中,第 iii 行应包含一个整数,表示第 iii 个查询后 aaa 中所有元素的总和。

    输入输出样例 #1

    输入 #1

    5 3
    1 6 2 4 6
    6 6 3
    2 2 3
    3 3 5

    输出 #1

    19
    13
    14
    20

    输入输出样例 #2

    输入 #2

    6 4
    929 121 5 3 919 72
    1 133 0
    70 79 0
    900 999 0
    1 1000 0

    输出 #2

    2049
    1848
    1848
    0
    0

    输入输出样例 #3

    输入 #3

    6 5
    7 72 727 123 321 9
    7 9 10
    10 72 727
    111 222 30
    123 727 99
    111 222 333

    输出 #3

    1259
    1263
    3352
    3259
    525
    525

    说明/提示

    子任务

    对于所有测试用例,输入将满足以下约束条件:

    • 1≤n≤200 0001 \\leq n \\leq 200\\,0001≤n≤200000
    • 0≤q≤200 0000 \\leq q \\leq 200\\,0000≤q≤200000
    • 0≤a[i]≤1090 \\leq a[i] \\leq 10^90≤a[i]≤109 对于所有 1≤i≤n1 \\leq i \\leq n1≤i≤n
    • 0≤x[j]≤1090 \\leq x[j] \\leq 10^90≤x[j]≤109 对于所有 1≤j≤q1 \\leq j \\leq q1≤j≤q
    • 0≤l[j]≤r[j]≤1090 \\leq l[j] \\leq r[j] \\leq 10^90≤l[j]≤r[j]≤109 对于所有 1≤j≤q1 \\leq j \\leq q1≤j≤q

    你的程序将在满足以下特殊性质的输入数据上进行测试:

    子任务分值特殊性质
    000 000 样例
    111 555 q=0q = 0q=0
    222 121212 n,q≤2000n, q \\leq 2000n,q≤2000
    333 212121 l[j]=r[j]≤200 000l[j] = r[j] \\leq 200\\,000l[j]=r[j]≤200000 且 a[i],x[j]≤200 000a[i], x[j] \\leq 200\\,000a[i],x[j]≤200000
    444 131313 l[j]=r[j]l[j] = r[j]l[j]=r[j]
    555 161616 x[j]=0x[j] = 0x[j]=0
    666 333333 无

    样例 1 解释

    此样例适用于子任务 2,3,4,62, 3, 4, 62,3,4,6。

    样例 2 解释

    此样例适用于子任务 2,5,62, 5, 62,5,6。

    样例 3 解释

    此样例适用于子任务 2,62, 62,6。

    在所有查询之前,数组 aaa 为 [7,72,727,123,321,9][7, 72, 727, 123, 321, 9][7,72,727,123,321,9],总和为 125912591259。

    第一次查询后,数组 aaa 变为 [10,72,727,123,321,10][10, 72, 727, 123, 321, 10][10,72,727,123,321,10],总和为 126312631263。

    第二次查询后,数组 aaa 变为 [727,727,727,123,321,727][727, 727, 727, 123, 321, 727][727,727,727,123,321,727],总和为 335233523352。

    第三次查询后,数组 aaa 变为 [727,727,727,30,321,727][727, 727, 727, 30, 321, 727][727,727,727,30,321,727],总和为 325932593259。

    第四次查询后,数组 aaa 变为 [99,99,99,30,99,99][99, 99, 99, 30, 99, 99][99,99,99,30,99,99],总和为 525525525。

    第五次查询后,数组 aaa 变为 [99,99,99,30,99,99][99, 99, 99, 30, 99, 99][99,99,99,30,99,99],总和为 525525525。

    C++实现

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    struct node{
    int l,r;
    mutable ll v;
    node(int a=0,int b=–1,ll c=0):l(a),r(b),v(c){}
    friend bool operator<(node a,node b){return a.l<b.l;}
    };
    set<node>s;ll ans;
    auto split(ll pos){
    auto it=s.lower_bound(node(pos));
    if(it!=s.end()&&it->l==pos)return it;
    it—;ll l=it->l,r=it->r,v=it->v;
    s.erase(it),s.insert(node(l,pos–1,v));
    return s.insert(node(pos,r,v)).first;
    }
    void update(ll d,ll k){
    auto it2=split(d+1),it1=split(d);
    for(auto it=it1;it!=it2;it++)it->v+=k,ans+=d*k;//X的出现次数的更新
    }
    ll assign(ll l,ll r,ll k){
    ll sum=0;
    auto it2=split(r+1),it1=split(l);
    for(auto it=it1;it!=it2;it++)
    {
    ans-=(it->r+it->l)*(it->r–it->l+1)/2*it->v;//原来的出现次数消失了,更新权值和
    sum+=(it->r–it->l+1)*it->v;//每个数的出现次数都要给到X
    }
    s.erase(it1,it2),s.insert(node(l,r,0));
    update(k,sum);return ans;
    }
    int main(){
    ll n,q,x;
    scanf("%lld%lld",&n,&q);
    s.insert(node(0,1e9,0));//一开始的区间
    for(ll i=1;i<=n;i++)scanf("%lld",&x),update(x,1);//出现次数加一
    printf("%lld\\n",ans);
    while(q—){
    ll l,r,x;
    scanf("%lld%lld%lld",&l,&r,&x);
    printf("%lld\\n",assign(l,r,x));
    }
    return 0;
    }

    在这里插入图片描述

    后续

    接下来我会不断用C++来实现信奥比赛中的算法题、GESP考级编程题实现、白名单赛事考题实现,记录日常的编程生活、比赛心得,感兴趣的请关注,我后续将继续分享相关内容

    赞(0)
    未经允许不得转载:网硕互联帮助中心 » 打卡信奥刷题(3664)用C++实现信奥题 P12194 [NOISG 2025 Prelim] Snacks
    分享到: 更多 (0)

    评论 抢沙发

    评论前必须登录!