题意:
题意翻译
题目描述
数组 a 有n 个元素,需要进行 q 次操作。
操作1:将第 i号元素改为x
操作2:将数组中所有元素改为x
每次操作完成后,输出当前数组中所有元素的总和。
输入格式
第一行两个整数 n,q(1≤n,q≤2×105)
第二行n个整数,表示 aa 中的元素(1≤ai≤109)
接下来有q行,首先输入一个整数 t(t∈1,2)
若 t=1,接着输入两个整数i,x(1≤i≤n,1≤x≤109)
若 t=2,接着输入一个整数 x(1≤x≤109)
输出格式
共 q 行,每行一个整数,表示当前数组 a 中所有元素的和
思路:
起初并没有想到线段树的模板哎,觉得应该就是一个简单的思维题,毕竟只是b,然后开始就开始想两个操作有没有可以简化或者说是记录的方法降低复杂度。
t=1的时候是单点修改,那么对于之前存好的和,只是改变了一个点,所以不难实现,直接改变即可。
那t=2的时候全部改变,和很好求,我的思路就是在t=2全部改变的时候额外加个时间点,仔细想:①如果在操作2之后对于单点修改,那么只需要判断一下对于当前位置i,最近的一次单点修改时间是在上次操作2之前还是之后就行了,就可以确定它的值,而不需要具体改变。
可能比较难想,但简而言之就是增加一个时间变量,然后再存储最近的一次操作2的值,如果对于当前位置最近的操作1出现在操作2之后,那么取数组原本的值,否则取最近的一次操作2的值~
还不理解可以看代码分析一下~挺好的小思维题
#include<bits/stdc++.h>
#define bug(a) cout<<"bug1 : "<<a<<endl;
#define bugg(a,b) cout<<"bug2 : "<<a<<" "<<b<<endl;
using namespace std;
#define int long long
const int maxn=2e5+1000;
struct node{
int idx,t1,value;
}mo[maxn];
signed main()
{
int n,i,j,q,t,idx,x,pret=-1,sum=0,prev=0;
cin>>n>>q;
for(i=1;i<=n;i++)
{
cin>>mo[i].value;
sum+=mo[i].value;
mo[i].t1=0;
}
// cout<<mo[1].value<<endl;
for(i=1;i<=q;i++)
{
cin>>t;
// cout<<sum<<endl;
if(t==1)
{
cin>>idx>>x;
if(mo[idx].t1>pret)
{
sum-=mo[idx].value;
sum+=x;
}
else
{
sum-=prev;
sum+=x;
}
mo[idx].value=x;
mo[idx].t1=i;
}
else
{
cin>>x;
pret=i;
prev=x;
sum=x*n;
}
cout<<sum<<endl;
}
return 0;
}
/*
32
6 6 6 6 4 4 ---6
4 4 4 4 4 4 4 4 ---8
34
6 6 6 6 6 4 ----7
4 4 4 4 4 4 4 6 --8
36
6 6 6 6 6 6 ----6
4 4 4 4 4 4 4 4 4 ----9
两个6 是三个
*/