您的位置:首页 > 其它

51nod 1394 差和问题(算法马拉松8)

2015-11-30 16:05 417 查看
有一个集合S,初始状态下有n个元素,对他进行如下操作:

1、向S里面添加一个值为v的元素。输入格式为1 v

2、向S里面删除一个值为v的元素。输入格式为2 v

3、询问S里面的元素两两之差绝对值之和。输入格式为3

对于样例,

操作3,|1-2|+|1-3|+|2-3|=4

操作1 4之后,集合中的数字为1 2 3 4

操作3,|1-2|+|1-3|+|2-3|+|1-4|+|2-4|+|3-4|=10

操作2 2之后,集合中的数字为1 3 4

操作3,|1-3|+|1-4|+|3-4|=6

Input
第一行输入两个整数n,Q表示集合中初始元素个数和操作次数。(1<=n,Q<=100,000)
第二行给出n个整数a[0],a[1],a[2],…,a[n-1],表示初始集合中的元素。(0<=a[i]<=1,000,000,000)
接下来Q行,每行一个操作。(0<=v<=1,000,000,000)


Output
对于第2类操作,如果集合中不存在值为v的元素可供删除,输出-1。
对于第3类操作,输出答案。


Input示例
3 5
1 2 3
3
1 4
3
2 2
3


Output示例

4
10
6


解题思路

离散化+树状数组,对每次1,2操作,用树状数组要统计比它大的个数和比它小的个数

代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn=200000+100;
struct node
{
int id;
long long v;
}q[maxn];
long long a[maxn*4];
int b[maxn*4];
long long t[maxn];
long long cur[maxn];
int cou[maxn];
long long low(int k)
{
return k&(-k);
}
void update(int k,long long v,int v2)
{
while(k<maxn)
{
a[k]+=v;
b[k]+=v2;
k+=low(k);
}
}
long long anss,ansn;
long long sums(int k)
{
anss=0,ansn=0;
while(k>0)
{
anss+=a[k];
ansn+=b[k];
k-=low(k);
}
}
int main()
{
int n,qu;
while(~scanf("%d%d",&n,&qu))
{
for(int i=0; i<n; i++)
{
scanf("%I64d",&t[i]);
cur[i]=t[i];
}
int cnt=n;
for(int i=0; i<qu; i++)
{
scanf("%d",&q[i].id);
if(q[i].id!=3)
{
scanf("%I64d",&q[i].v);
cur[cnt]=q[i].v;
cnt++;
}
}
sort(cur,cur+cnt);
int all=unique(cur,cur+cnt)-cur;
long long sum=0,ans=0;
int sumn=0;
int temp;
for(int i=0;i<n;i++)
{
temp=lower_bound(cur,cur+all,t[i])-cur+1;
cou[temp]++;
sumn++;
update(temp,t[i],1);
sum+=t[i];
sums(temp);
ans=ans+(t[i]*(ansn*2-sumn)-2*anss+sum);
// cout<<ans<<endl;
}
long long cwt;
for(int i=0;i<qu;i++)
{
if(q[i].id==1)
{
//cout<<q[i].id<<"  "<<q[i].v<<endl;
temp=lower_bound(cur,cur+all,q[i].v)-cur+1;
// cout<<temp<<endl;
update(temp,q[i].v,1);
cou[temp]++;
sum+=q[i].v;
sumn++;
sums(temp);
// cout<<q[i].v*(ansn*2-sumn)-2*anss+sum<<endl;
// cout<<anss<<"  "<<ansn<<"  "<<sum<<"  "<<q[i].v<<endl;
ans=ans+(q[i].v*(ansn*2-sumn)-2*anss+sum);
// cout<<ans<<endl;
}
else if(q[i].id==2)
{
temp=lower_bound(cur,cur+all,q[i].v)-cur+1;
if(cou[temp]==0)
{
printf("-1\n");
}
else
{
sums(temp);
ans=ans-(q[i].v*(ansn*2-sumn)-2*anss+sum);
update(temp,-q[i].v,-1);
cou[temp]--;
sum-=q[i].v;
sumn--;
}
}
else if(q[i].id==3)
{
printf("%I64d\n",ans);
}
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: