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

有一个集合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 
#include 
#include 
#include 
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(k0)
    {
        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





你可能感兴趣的:(51nod,编程,算法,acm,algorithm)