每次修改,都能直接更新答案。数据可以用树状数组或线段树维护。
#include<bits/stdc++.h>
using namespace std;
const int MAXN=200100;
char op[MAXN];
int discnum;
long long disc[MAXN],v[MAXN];
long long c[2][2][MAXN],a[MAXN];
void update(int num,int k,int x,long long d){while(x<=discnum)c[num][k][x]+=d,x+=x&-x;}
long long _query(int num,int k,int x){long long s=0;while(x)s+=c[num][k][x],x-=x&-x;return s;}
void add(int num,int l,int r,long long p)
{
update(num,0,l,p);update(num,0,r+1,-p);
update(num,1,l,p*l);update(num,1,r+1,-(r+1)*p);
}
long long query(int num,int l,int r)
{
if(l>r)
return 0;
return (r+1)*_query(num,0,r)-_query(num,1,r)-(l*_query(num,0,l-1)-_query(num,1,l-1));
}
int mp(long long x)
{
return lower_bound(disc,disc+discnum,x)-disc+1;
}
void read(long long &a){
char ch;while(!((ch=getchar())>='0')&&(ch<='9'));
a=ch-'0';while(((ch=getchar())>='0')&&(ch<='9'))a*=10,a+=ch-'0';
}
inline void prin_d(long long x)
{
if (x > 9)
{
prin_d(x / 10);
}
putchar(x % 10 + '0');
return ;
}
int main()
{
long long n,q,i,ans,index,num1,num2;
while(~scanf("%lld%lld",&n,&q))
{
memset(c,0,sizeof(c));
discnum=0;
for(i=0;i<n;i++)
{
read(a[i]);
disc[discnum++]=a[i];
}
for(i=0;i<q;i++)
{
scanf(" %c",&op[i]);
if(op[i]!='3')
{
read(v[i]);
disc[discnum++]=v[i];
}
}
sort(disc,disc+discnum);
discnum=unique(disc,disc+discnum)-disc;
sort(a,a+n);
ans=0;
for(i=0;i<n;i++)
{
index=mp(a[i]);
add(0,index,index,1);
add(1,index,index,a[i]);
ans+=(i+i-(n-1))*a[i];
}
for(i=0;i<q;i++)
{
if(op[i]=='1')
{
index=mp(v[i]);
num1=query(0,1,index-1);
num2=query(0,index+1,discnum);
add(0,index,index,1);
add(1,index,index,v[i]);
ans+=(num1-num2)*v[i];
ans+=query(1,index+1,discnum);
ans-=query(1,1,index-1);
}
else if(op[i]=='2')
{
index=mp(v[i]);
if(!query(0,index,index))
{
printf("-1\n");
continue;
}
num1=query(0,1,index-1);
num2=query(0,index+1,discnum);
add(0,index,index,-1);
add(1,index,index,-v[i]);
ans-=(num1-num2)*v[i];
ans-=query(1,index+1,discnum);
ans+=query(1,1,index-1);
}
else if(op[i]=='3')
{
prin_d(ans);
puts("");
}
}
}
}