参考链接:http://blog.csdn.net/dyx404514/article/details/8817717

写的很详细,这里就不再赘述,附上我的代码。

  1. #include <iostream>
  2. #include <stdio.h>
  3. #include <algorithm>
  4. #define lson rt<<1,L,mid
  5. #define rson rt<<1|1,mid+1,R
  6. /*
  7. AC
  8. http://blog.csdn.net/dyx404514/article/details/8817717
  9. */
  10. using namespace std;
  11. const int maxn=;
  12. int n,m;
  13. int nn; //最后离散后的点的个数
  14. long long val[maxn*]; //存储所有数据
  15. long long hashval[maxn*]; //存储离散后的数据
  16. long long a[maxn],aa[maxn]; //存储初始序列
  17. int pos[maxn]; //存储初始序列在hashval中的位置
  18. int cnt=-; //用于离散时,统计总共有多少个数
  19. int idx=; //用于建树时,获取初始的n个坐标值在hashval中位置的索引
  20. struct Node{
  21. int num; //该区间有多少个点。
  22. long long sum; //该区间点的横坐标之和。
  23. long long ans; //该区间每一对点的距离之和。
  24. }tree[maxn<<];
  25.  
  26. struct Query{
  27. int t,p,d;
  28. long long l,r;
  29. }q[maxn];
  30.  
  31. /*
  32. 注意:这里二分查找时,用mark标记是查找>=m的数的位置,还是查找<=m的数的位置。
  33. 当更新的时候,mark=2即可。
  34. 当查询时,查找l的时候,由于l可能不存在,所以我们查找的时候需要查找>=l的最近的数的位置,此时mark=1;
  35. 查找r的时候,由于r可能不存在,所以我们查找的时候需要查找<=r的最近的数的位置,此时mark=2
  36. */
  37. int binarySearch(long long m,int mark,int length){
  38. int l=,r=length+,mid;
  39. while(r-l>){
  40. mid=(l+r)>>;
  41. if(hashval[mid]<=m)
  42. l=mid;
  43. else
  44. r=mid;
  45. }
  46. if(hashval[l]==m)
  47. return l;
  48. if(mark==)
  49. return l+;
  50. else
  51. return l;
  52. }
  53.  
  54. void pushUp(Node &rt,Node &ls,Node &rs){
  55. rt.num=ls.num+rs.num;
  56. rt.sum=ls.sum+rs.sum;
  57. rt.ans=ls.num*rs.sum-rs.num*ls.sum+ls.ans+rs.ans; //公式的话,很容易就能推出,这里就不详细说了
  58. }
  59. void build(int rt,int L,int R){
  60. if(L==R){
  61. tree[rt].num=tree[rt].sum=tree[rt].ans=;
  62. if(idx<=n && L==pos[idx]){
  63. tree[rt].num=;
  64. tree[rt].sum=aa[idx];
  65. tree[rt].ans=;
  66. idx++;
  67. }
  68. return;
  69. }
  70. int mid=(L+R)>>;
  71. build(lson);
  72. build(rson);
  73. pushUp(tree[rt],tree[rt<<],tree[rt<<|]);
  74. }
  75. /*
  76. op=1即是加入一个数
  77. op=0即使去除一个数
  78. */
  79. void update(int rt,int L,int R,int x,int op,int val){
  80. if(L==R){
  81. if(op==){
  82. tree[rt].num=;
  83. tree[rt].sum=val;
  84. tree[rt].ans=;
  85. }
  86. else{
  87. tree[rt].num=tree[rt].sum=tree[rt].ans=;
  88. }
  89. return;
  90. }
  91. int mid=(L+R)>>;
  92. if(x<=mid)
  93. update(lson,x,op,val);
  94. else
  95. update(rson,x,op,val);
  96. pushUp(tree[rt],tree[rt<<],tree[rt<<|]);
  97. }
  98. Node query(int rt,int L,int R,int l,int r){
  99. if(l<=L&&R<=r){
  100. return tree[rt];
  101. }
  102. Node tmp,a,b;
  103. int mid=(L+R)>>;
  104. if(r<=mid)
  105. tmp=query(lson,l,r);
  106. else if(l>mid)
  107. tmp=query(rson,l,r);
  108. else{
  109. a=query(lson,l,mid);
  110. b=query(rson,mid+,r);
  111. pushUp(tmp,a,b);
  112. }
  113. return tmp;
  114. }
  115. int main()
  116. {
  117. int v,t,p,d;
  118. int x,y;
  119. long long l,r;
  120. scanf("%d",&n);
  121. for(int i=;i<=n;i++){
  122. scanf("%d",&v);
  123. a[i]=v;
  124. aa[i]=v;
  125. val[++cnt]=v;
  126. }
  127. scanf("%d",&m);
  128. for(int i=;i<=m;i++){
  129. scanf("%d",&t);
  130. if(t==){
  131. scanf("%d%d",&p,&d);
  132. q[i].t=t;
  133. q[i].p=p;
  134. q[i].d=d;
  135. aa[p]+=d; //是累加的
  136. val[++cnt]=aa[p];
  137. }
  138. else{
  139. scanf("%I64d%I64d",&l,&r);
  140. q[i].t=t;
  141. q[i].l=l; //也可以将查询的l和r加入到离散的数据中去,这样二分查找的时候就不用考虑l和r不存在的问题,
  142. q[i].r=r; //查找时,当hashval[mid]==m时返回mid就行,当然这样数组相对就要开大了。
  143. }
  144. }
  145. sort(val,val+cnt+);
  146. //for(int i=0;i<=cnt;i++)
  147. // printf("%I64d ",val[i]);
  148. //printf("\n");
  149.  
  150. nn=;
  151. hashval[++nn]=val[];
  152. for(int i=;i<=cnt;i++){
  153. if(val[i]!=val[i-]){
  154. hashval[++nn]=val[i];
  155. }
  156. }
  157. //for(int i=1;i<=nn;i++)
  158. // printf("%I64d ",hashval[i]);
  159. //printf("\n");
  160.  
  161. for(int i=;i<=n;i++)
  162. aa[i]=a[i];
  163. sort(aa+,aa+n+);
  164.  
  165. //这里pos数组存储的是初始序列在离散后的数组hashval中的位置,用于建树的初始化
  166. //也可以不采用该方法,在建树时都设为0,然后在对初始序列一个个update即可
  167. for(int i=;i<=n;i++){
  168. pos[i]=binarySearch(aa[i],,nn);
  169. }
  170.  
  171. build(,,nn);
  172. for(int i=;i<=m;i++){
  173. if(q[i].t==){
  174. x=binarySearch(a[q[i].p],,nn);
  175. update(,,nn,x,,);
  176. a[q[i].p]+=q[i].d;
  177. x=binarySearch(a[q[i].p],,nn);
  178. update(,,nn,x,,a[q[i].p]);
  179. }
  180. else{
  181. x=binarySearch(q[i].l,,nn);
  182. y=binarySearch(q[i].r,,nn);
  183. //printf("%I64d %I64d %d %d\n",q[i].l,q[i].r,x,y);
  184. if(x>nn||y<||x>y)
  185. printf("0\n"); //可能会遇到l>r的情况,参见代码后面的例子
  186. else
  187. printf("%I64d\n",query(,,nn,x,y).ans);
  188. }
  189. }
  190. return ;
  191. }
  192.  
  193. /*
  194. 4
  195. 20 30 10 -20
  196. 5 x y
  197. 2 -25 -20 2 2
  198. 1 2 -40
  199. 2 21 25 6 5 (这里l>r,一开始忽略了这种情况,导致运行到第二个程序的时候,查询一直往下,无法停止,导致MLE)
  200. 1 4 -10
  201. 2 -35 -30 1 1
  202.  
  203. 附:叶子节点对应的数据:
  204. -30 -20 -10 10 20 30
  205. */

codeforces 295E Yaroslav and Points (离线操作+离散化+区间合并)的更多相关文章

  1. Codeforces 295E Yaroslav and Points 线段树

    Yaroslav and Points 明明区间合并一下就好的东西, 为什么我会写得这么麻烦的方法啊啊啊. #include<bits/stdc++.h> #define LL long ...

  2. CF 295E Yaroslav and Points(Splay)

    题目大意: 两个操作 1 id op  把id的位置+op 2 id op  查询在[id.op]之间的全部的数的差 思路: 关键是pushup函数. 自己退一下会发现.跟区间的总和,区间的节点个数有 ...

  3. Codeforces Round #276 (Div. 1) E. Sign on Fence (二分答案 主席树 区间合并)

    链接:http://codeforces.com/contest/484/problem/E 题意: 给你n个数的,每个数代表高度: 再给出m个询问,每次询问[l,r]区间内连续w个数的最大的最小值: ...

  4. codeforces Good bye 2016 E 线段树维护dp区间合并

    codeforces Good bye 2016 E 线段树维护dp区间合并 题目大意:给你一个字符串,范围为‘0’~'9',定义一个ugly的串,即串中的子串不能有2016,但是一定要有2017,问 ...

  5. CodeForces - 357C Knight Tournament 伪并查集(区间合并)

    Knight Tournament Hooray! Berl II, the king of Berland is making a knight tournament. The king has a ...

  6. CodeForces - 566D Restructuring Company 并查集的区间合并

    Restructuring Company Even the most successful company can go through a crisis period when you have ...

  7. CodeForces - 587E[线段树+线性基+差分] ->(线段树维护区间合并线性基)

    题意:给你一个数组,有两种操作,一种区间xor一个值,一个是查询区间xor的结果的种类数 做法一:对于一个给定的区间,我们可以通过求解线性基的方式求出结果的种类数,而现在只不过将其放在线树上维护区间线 ...

  8. 【bzoj2653】middle 可持久化线段树区间合并

    题目描述 一个长度为n的序列a,设其排过序之后为b,其中位数定义为b[n/2],其中a,b从0开始标号,除法取下整.给你一个长度为n的序列s.回答Q个这样的询问:s的左端点在[a,b]之间,右端点在[ ...

  9. POJ 2482 Stars in Your Window (线段树区间合并+扫描线)

    这题开始一直被矩形框束缚了,想法一直都是枚举线,但是这样枚举都需要O(n^2)...但是看了别人的思路,感觉这题思想真心很好(PS:开头好浪漫的描述啊,可惜并没有什么用)  题意就是在平面上给你一些星 ...

随机推荐

  1. Change http port in bitnami stack

    My case goes like this. I installed bitnami redmine first with port 80 for http service, but got pro ...

  2. js生成 1-100 不重复随机数

    var count=100; var a=new Array(); for(var i=0;i<100;i++){ a[i]=i+1; } a.sort(function(){ return 0 ...

  3. Git错误non-fast-forward后的冲突解决(转载)

    文章转载自:http://blog.csdn.net/chain2012/article/details/7476493 当要push代码到git时,出现提示: error:failed to pus ...

  4. 基于jQuery的判断iPad、iPhone、Android是横屏还是竖屏

    function orient() {if (window.orientation == 90 || window.orientation == -90) {//ipad.iphone竖屏:Andri ...

  5. js 数组去重复键

    Array.prototype.deleteEle = function() { var newArr = this; for (var i = newArr.length - 1; i >= ...

  6. C语言的sizeof

    今天帮同学想用C实现数组的折半查找,本来算法挺简单的,可是折腾了好几个小时才发现问题在哪,这个sizeof坑人不浅啊. #include<stdio.h> void m(int []); ...

  7. django 更新model

    修改models.py 中对应的class 在admin.py 中 增加 admin.site.register(WafDevice) 进入dbshell python manage.py dbshe ...

  8. JMS概述

    [1.面向消息的中间件]顾名思义,面向消息的中间件就是通过使用消息(而不是命令)将企业内的组件连接起来的系统.例如库存系统可能会与工资和会计系统进行通信,如果使用面向消息的中间件将他们连接在一起,就可 ...

  9. Linux 批量解压gz包

    [root@yoon export]# vi gunzip.sh !/bin/bashpath=/export/backup ----备份文件目录路径 for i in `ls ${path}/*`d ...

  10. MySQL 多实例数据库还原脚本-备份集与端口对应

    版本:5.5.14 OS: ConetOS 6.3 1.创建recover.sh [root@yoon  export]# vi  recover.sh #!/bin/bash bakdir=/exp ...