1394 差和问题
Posted SJY
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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 差和问题的主要内容,如果未能解决你的问题,请参考以下文章