1394 差和问题

Posted SJY

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了1394 差和问题相关的知识,希望对你有一定的参考价值。

1394 差和问题

基准时间限制:1 秒 空间限制:131072 KB

有一个多重集合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
思路:离散化+数状数组;
维护两个树状数组,一个为区间的和,另一个为区间个数,然后离线查询。插入和删除一个数字的时候要统计一下这个对答案的影响。当前数字为x,比当前数字小的有cnt个,总和为sum,那么这一部分对答案的影响是x*cnt-sum.对于求比当前数字大的数字类似的道理。
  1 #include<stdio.h>
  2 #include<algorithm>
  3 #include<iostream>
  4 #include<stdlib.h>
  5 #include<queue>
  6 #include<string.h>
  7 #include<math.h>
  8 #include<map>
  9 using namespace std;
 10 typedef long long LL;
 11 LL num[100005];
 12 typedef struct node
 13 {
 14         LL x;
 15         int op;
 16         int  id;
 17 } ss;
 18 typedef struct pp
 19 {
 20         LL x;
 21         LL id;
 22 } ap;
 23 ss ask[100005];
 24 map<LL,int>my;
 25 LL ac[400000];
 26 int id[100005];
 27 LL bit_ans[200005];
 28 LL bit_sum[200005];
 29 LL sum1(int i);
 30 void add1(int i,LL x,int n);
 31 LL sum2(int i);
 32 void add2(int i,LL x,int n);
 33 LL akk[100005];
 34 int main(void)
 35 {
 36         int n,Q;
 37         scanf("%d %d",&n,&Q);
 38         int i,j;
 39         my.clear();
 40         int cn = 0;
 41         memset(bit_ans,0,sizeof(bit_ans));
 42         memset(bit_sum,0,sizeof(bit_sum));
 43         for(i = 0; i < n; i++)
 44         {
 45                 scanf("%lld",&num[i]);
 46                 ac[cn++] = num[i];
 47         }
 48         for(i = 1; i <= Q; i++)
 49         {
 50                 int x,y;
 51                 scanf("%d",&ask[i].op);
 52                 if(ask[i].op != 3)
 53                 {
 54                         scanf("%lld",&ask[i].x);
 55                         ac[cn++] = ask[i].x;
 56                 }
 57                 ask[i].id = i;
 58         }//printf("1\n");
 59         sort(num,num+n);
 60         sort(ac,ac+cn);
 61         int acc = 1;
 62         LL x = ac[0];
 63         my[x] = 1;
 64         for(i = 1; i < cn; i++)
 65         {
 66                 if(x!=ac[i])
 67                 {
 68                         acc++;
 69                         x= ac[i];
 70                         my[x] = acc;
 71                 }
 72         }
 73         LL summ = 0;
 74         for(i = 0; i < n; i ++)
 75         {
 76                 int uv = my[num[i]];
 77                 summ += sum2(uv-1)*num[i] - sum1(uv-1);
 78                 add1(uv,num[i],acc);
 79                 add2(uv,1,acc);
 80         }
 81         akk[0]=summ;
 82         for(i = 1; i <= Q; i++)
 83         {
 84                 if(ask[i].op==2)
 85                 {
 86                         int ic = my[ask[i].x];
 87                         LL a = sum2(ic)-sum2(ic-1);
 88                         if(!a){printf("-1\n");akk[i] = akk[i-1];}
 89                         else
 90                         {
 91                                 LL smal_x1 = sum2(ic-1);
 92                                 LL smal_y1 = sum1(ic-1);
 93                                 LL maxx_x1 = sum2(acc)-sum2(ic);
 94                                 LL maxx_y1 = sum1(acc)-sum1(ic);
 95                                 akk[i] = akk[i-1] - (smal_x1)*ask[i].x + smal_y1 - maxx_y1 + maxx_x1*ask[i].x;
 96                                 add1(ic,-ask[i].x,cn);
 97                                 add2(ic,-1,cn);
 98                         }
 99                 }
100                 else if(ask[i].op == 1)
101                 {
102                         int ic = my[ask[i].x];
103                         LL smal_x1 = sum2(ic-1);
104                         LL smal_y1 = sum1(ic-1);
105                         LL maxx_x1 = sum2(acc)-sum2(ic);
106                         LL maxx_y1 = sum1(acc)-sum1(ic);
107                         akk[i] = akk[i-1] + (smal_x1)*ask[i].x - smal_y1 + maxx_y1 - maxx_x1*ask[i].x;
108                         add1(ic,ask[i].x,cn);
109                         add2(ic,1,cn);
110                 }
111                 else
112                 {
113                         akk[i] = akk[i-1];
114                         printf("%lld\n",akk[i]);
115                 }
116         }
117         return 0;
118 }
119 LL sum1(int i)
120 {
121         LL s = 0;
122         while(i>0)
123         {
124                 s+=bit_sum[i];
125                 i -= i & -i;
126         }
127         return s;
128 }
129 void add1(int i,LL x,int n)
130 {
131         while(i <= n)
132         {
133                 bit_sum[i] += x;
134                 i += i&(-i);
135         }
136 }
137 LL sum2(int i)
138 {
139         LL s = 0;
140         while(i>0)
141         {
142                 s+=bit_ans[i];
143                 i -= i & -i;
144         }
145         return s;
146 }
147 void add2(int i,LL x,int n)
148 {
149         while(i <= n)
150         {
151                 bit_ans[i] += x;
152                 i += i&(-i);
153         }
154 }

 

以上是关于1394 差和问题的主要内容,如果未能解决你的问题,请参考以下文章

51nod1394 差和问题

UVa 1394 约瑟夫问题的变形

我正在尝试计算 R 中每年的标准差和平均回报

hihoCoder 1394 : 网络流四·最小路径覆盖 (网络流学习#4 记录)

九度 题目1394:五连击数组

N阶差和N阶差