P12194 [NOISG 2025 Prelim] Snacks
题目描述
Shor 小鸭已经准备了 nnn 个小吃盘子,准备一边看电影一边享用!第 iii 个盘子最初装有一个美味值为 a[i]a[i]a[i] 的小吃。
你需要处理 qqq 个查询。在第 jjj 个查询中,Shor 将按顺序执行以下两个操作:
在处理任何查询之前,以及每次处理完查询之后,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考级编程题实现、白名单赛事考题实现,记录日常的编程生活、比赛心得,感兴趣的请关注,我后续将继续分享相关内容
网硕互联帮助中心






评论前必须登录!
注册