51nod1394 差和问题
Posted BBChq
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了51nod1394 差和问题相关的知识,希望对你有一定的参考价值。
我只会用线段树写。。。不喜欢树状数组。。其实跑的也不算慢?然后各种*的时候忘了longlong一直WA。。。药丸!
而且我不怎么会用map离散化。。。那么就sort+unique
#include<cstdio> #include<cstring> #include<cctype> #include<algorithm> using namespace std; #define rep(i,s,t) for(int i=s;i<=t;i++) #define dwn(i,s,t) for(int i=s;i>=t;i--) #define clr(x,c) memset(x,c,sizeof(x)) #define ll long long #define lson l,mid,x<<1 #define rson mid+1,r,x<<1|1 int read(){ int x=0;char c=getchar(); while(!isdigit(c)) c=getchar(); while(isdigit(c)) x=x*10+c-‘0‘,c=getchar(); return x; } const int nmax=1e5+5; const int inf=0x7f7f7f7f; ll sm[nmax<<3],col[nmax<<3];int a[nmax<<1],b[nmax<<1],ct[nmax<<1]; struct node{ int u,v; }; node ns[nmax]; void update(int p,int ad,int bd,int l,int r,int x){ if(l==r) { col[x]+=ad,sm[x]+=bd;return ; } int mid=(l+r)>>1; p<=mid?update(p,ad,bd,lson):update(p,ad,bd,rson); sm[x]=sm[x<<1]+sm[x<<1|1];col[x]=col[x<<1]+col[x<<1|1]; } struct nd{ int u;ll v; nd(int u,ll v):u(u),v(v){}; nd(){}; }; nd query(int tl,int tr,int l,int r,int x){ if(tl<=l&&tr>=r) return nd(col[x],sm[x]); ll tm=0;int tc=0,mid=(l+r)>>1;nd o; if(tl<=mid) o=query(tl,tr,lson),tc+=o.u,tm+=o.v; if(tr>mid) o=query(tl,tr,rson),tc+=o.u,tm+=o.v; return nd(tc,tm); } void print(int l,int r,int x){ printf("%d %d %d\n",l,r,sm[x]); if(l==r) return ; int mid=(l+r)>>1; print(lson);print(rson); } int main(){ int n=read(),m=read(),u,v,d,cnt=n; rep(i,1,n) a[i]=b[i]=read(); rep(i,1,m){ ns[i].u=read();if(ns[i].u!=3) ns[i].v=read(),a[++cnt]=b[cnt]=ns[i].v; } sort(b+1,b+cnt+1); cnt=unique(b+1,b+cnt+1)-b-1; rep(i,1,n) a[i]=lower_bound(b+1,b+cnt+1,a[i])-b; rep(i,1,n) update(a[i],1,b[a[i]],1,cnt,1),ct[a[i]]++; ll tm;nd o; tm=0; rep(j,2,cnt) { o=query(1,j-1,1,cnt,1); tm+=(ll)ct[j]*((ll)b[j]*o.u-o.v); } rep(i,1,m){ u=ns[i].u; if(u==3) printf("%lld\n",tm); else if(u==1){ v=lower_bound(b+1,b+cnt+1,ns[i].v)-b; ct[v]++;update(v,1,ns[i].v,1,cnt,1); if(v==1) o=nd(0,0);else o=query(1,v-1,1,cnt,1); tm+=(ll)b[v]*o.u-o.v+(sm[1]-o.v-(ll)b[v]*ct[v])-(ll)(col[1]-o.u-ct[v])*b[v]; }else{ v=lower_bound(b+1,b+cnt+1,ns[i].v)-b; if(!ct[v]) puts("-1"); else{ ct[v]--,update(v,-1,-ns[i].v,1,cnt,1); if(v==1) o=nd(0,0);else o=query(1,v-1,1,cnt,1); tm-=(ll)b[v]*o.u-o.v+(sm[1]-o.v-(ll)b[v]*ct[v])-(ll)(col[1]-o.u-ct[v])*b[v]; } } //printf("->_->\n");print(1,cnt,1); } return 0; }
有一个多重集合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
以上是关于51nod1394 差和问题的主要内容,如果未能解决你的问题,请参考以下文章