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

来源:互联网 发布:linux将目录打包 编辑:程序博客网 时间:2024/05/16 19:02

有一个集合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 51 2 331 432 23
Output示例
4106

解题思路
离散化+树状数组,对每次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;}





0 0
原创粉丝点击