题目链接<https://www.luogu.org/problemnew/show/P3374>
题解:
一共有两维,一维是操作的时间,一维是操作的位置。一开始时间是排好序的,只需要对位置这一维分治统计。
利用前缀和的思想,把答案记为sum[r]-sum[l-1],所以把查询操作拆成两个:r和l-1。
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=5e6+7;
int n,m,tot,num=0;
struct Node{
int tp,id;
ll val;
bool operator<(const Node a)const{
if(id==a.id) return tp<a.tp;
return id<a.id;
}
}a[N],b[N];
ll ans[N];
void cdq(int l,int r){
if(l==r) return;
int m=l+r>>1;
cdq(l,m);cdq(m+1,r);
int p=l,q=m+1,i=l;
ll sum=0;
while(p<=m&&q<=r){
if(a[p]<a[q]){
if(a[p].tp==1) sum+=a[p].val;
b[i++]=a[p++];
}
else{
if(a[q].tp==2) ans[a[q].val]-=sum;
else if(a[q].tp==3)ans[a[q].val]+=sum;
b[i++]=a[q++];
}
}
while(p<=m) b[i++]=a[p++];
while(q<=r){
if(a[q].tp==2) ans[a[q].val]-=sum;
else if(a[q].tp==3)ans[a[q].val]+=sum;
b[i++]=a[q++];
}
for(int i=l;i<=r;i++) a[i]=b[i];
}
int main()
{
scanf("%d%d",&n,&m);
for(ll i=1;i<=n;i++){
a[++tot].tp=1;a[tot].id=i;
scanf("%lld",&a[tot].val);
}
while(m--){
int tp;
scanf("%d",&tp);
if(tp==1){
a[++tot].tp=1;
scanf("%d%lld",&a[tot].id,&a[tot].val);
}
else{
int l,r;
scanf("%d%d",&l,&r);
num++;
a[++tot].tp=2;
a[tot].id=l-1;a[tot].val=num;
a[++tot].tp=3;
a[tot].id=r;a[tot].val=num;
}
}
cdq(1,tot);
for(ll i=1;i<=num;i++) printf("%lld\n",ans[i]);
}