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

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

#include <iostream>
#include <stdio.h>
#include <algorithm>
#define lson rt<<1,L,mid
#define rson rt<<1|1,mid+1,R
/*
AC
http://blog.csdn.net/dyx404514/article/details/8817717
*/
using namespace std;
const int maxn=;
int n,m;
int nn; //最后离散后的点的个数
long long val[maxn*]; //存储所有数据
long long hashval[maxn*]; //存储离散后的数据
long long a[maxn],aa[maxn]; //存储初始序列
int pos[maxn]; //存储初始序列在hashval中的位置
int cnt=-; //用于离散时,统计总共有多少个数
int idx=; //用于建树时,获取初始的n个坐标值在hashval中位置的索引
struct Node{
int num; //该区间有多少个点。
long long sum; //该区间点的横坐标之和。
long long ans; //该区间每一对点的距离之和。
}tree[maxn<<]; struct Query{
int t,p,d;
long long l,r;
}q[maxn]; /*
注意:这里二分查找时,用mark标记是查找>=m的数的位置,还是查找<=m的数的位置。
当更新的时候,mark=2即可。
当查询时,查找l的时候,由于l可能不存在,所以我们查找的时候需要查找>=l的最近的数的位置,此时mark=1;
查找r的时候,由于r可能不存在,所以我们查找的时候需要查找<=r的最近的数的位置,此时mark=2
*/
int binarySearch(long long m,int mark,int length){
int l=,r=length+,mid;
while(r-l>){
mid=(l+r)>>;
if(hashval[mid]<=m)
l=mid;
else
r=mid;
}
if(hashval[l]==m)
return l;
if(mark==)
return l+;
else
return l;
} void pushUp(Node &rt,Node &ls,Node &rs){
rt.num=ls.num+rs.num;
rt.sum=ls.sum+rs.sum;
rt.ans=ls.num*rs.sum-rs.num*ls.sum+ls.ans+rs.ans; //公式的话,很容易就能推出,这里就不详细说了
}
void build(int rt,int L,int R){
if(L==R){
tree[rt].num=tree[rt].sum=tree[rt].ans=;
if(idx<=n && L==pos[idx]){
tree[rt].num=;
tree[rt].sum=aa[idx];
tree[rt].ans=;
idx++;
}
return;
}
int mid=(L+R)>>;
build(lson);
build(rson);
pushUp(tree[rt],tree[rt<<],tree[rt<<|]);
}
/*
op=1即是加入一个数
op=0即使去除一个数
*/
void update(int rt,int L,int R,int x,int op,int val){
if(L==R){
if(op==){
tree[rt].num=;
tree[rt].sum=val;
tree[rt].ans=;
}
else{
tree[rt].num=tree[rt].sum=tree[rt].ans=;
}
return;
}
int mid=(L+R)>>;
if(x<=mid)
update(lson,x,op,val);
else
update(rson,x,op,val);
pushUp(tree[rt],tree[rt<<],tree[rt<<|]);
}
Node query(int rt,int L,int R,int l,int r){
if(l<=L&&R<=r){
return tree[rt];
}
Node tmp,a,b;
int mid=(L+R)>>;
if(r<=mid)
tmp=query(lson,l,r);
else if(l>mid)
tmp=query(rson,l,r);
else{
a=query(lson,l,mid);
b=query(rson,mid+,r);
pushUp(tmp,a,b);
}
return tmp;
}
int main()
{
int v,t,p,d;
int x,y;
long long l,r;
scanf("%d",&n);
for(int i=;i<=n;i++){
scanf("%d",&v);
a[i]=v;
aa[i]=v;
val[++cnt]=v;
}
scanf("%d",&m);
for(int i=;i<=m;i++){
scanf("%d",&t);
if(t==){
scanf("%d%d",&p,&d);
q[i].t=t;
q[i].p=p;
q[i].d=d;
aa[p]+=d; //是累加的
val[++cnt]=aa[p];
}
else{
scanf("%I64d%I64d",&l,&r);
q[i].t=t;
q[i].l=l; //也可以将查询的l和r加入到离散的数据中去,这样二分查找的时候就不用考虑l和r不存在的问题,
q[i].r=r; //查找时,当hashval[mid]==m时返回mid就行,当然这样数组相对就要开大了。
}
}
sort(val,val+cnt+);
//for(int i=0;i<=cnt;i++)
// printf("%I64d ",val[i]);
//printf("\n"); nn=;
hashval[++nn]=val[];
for(int i=;i<=cnt;i++){
if(val[i]!=val[i-]){
hashval[++nn]=val[i];
}
}
//for(int i=1;i<=nn;i++)
// printf("%I64d ",hashval[i]);
//printf("\n"); for(int i=;i<=n;i++)
aa[i]=a[i];
sort(aa+,aa+n+); //这里pos数组存储的是初始序列在离散后的数组hashval中的位置,用于建树的初始化
//也可以不采用该方法,在建树时都设为0,然后在对初始序列一个个update即可
for(int i=;i<=n;i++){
pos[i]=binarySearch(aa[i],,nn);
} build(,,nn);
for(int i=;i<=m;i++){
if(q[i].t==){
x=binarySearch(a[q[i].p],,nn);
update(,,nn,x,,);
a[q[i].p]+=q[i].d;
x=binarySearch(a[q[i].p],,nn);
update(,,nn,x,,a[q[i].p]);
}
else{
x=binarySearch(q[i].l,,nn);
y=binarySearch(q[i].r,,nn);
//printf("%I64d %I64d %d %d\n",q[i].l,q[i].r,x,y);
if(x>nn||y<||x>y)
printf("0\n"); //可能会遇到l>r的情况,参见代码后面的例子
else
printf("%I64d\n",query(,,nn,x,y).ans);
}
}
return ;
} /*
4
20 30 10 -20
5 x y
2 -25 -20 2 2
1 2 -40
2 21 25 6 5 (这里l>r,一开始忽略了这种情况,导致运行到第二个程序的时候,查询一直往下,无法停止,导致MLE)
1 4 -10
2 -35 -30 1 1 附:叶子节点对应的数据:
-30 -20 -10 10 20 30
*/

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. virtualbox安装增强包及配置共享文件夹

       因为需要在host及虚拟机间传输数据,想使用共享文件夹.但是单独设置了共享文件夹后在centos里找不到共享文件夹,看了下要安装增强包.好吧,顺 便也解决下鼠标切换的问题,省的老是按右CTL切换 ...

  2. 标签控制器,UITabBarController

    注意: 1.tabbar高度不可设置,可通过_tabbar.tabbar.frame设置tabbar的位置 2.tabbar不同页面添加同一个视图后其那面添加的不起作用,只有最后一个才具有所添加的仕途 ...

  3. Android Audio Play Out Channel

    1: 7嘴8舌 扬声器, 耳机, 和听筒 就是通过: audiomanager.setmode(AudioManager.MODE_IN_COMMUNICATION)audiomanager.setS ...

  4. jquery源码分析学习地址

    http://www.ccvita.com/121.htmljQuery工作原理解析以及源代码示例http://www.cnblogs.com/haogj/archive/2010/04/19/171 ...

  5. mysql主从复制-linux版本

    来自:http://www.osyunwei.com/archives/7269.html,改版 mysql主从复制本文采用的是centos6.5+mysql-5.6.23版本之前在 windows7 ...

  6. [转]Android在eclipse中的快捷键

    1.选中你要加注释的区域,用ctrl+shift+C 会加上//注释2.先把你要注释的东西选中,用shit+ctrl+/ 会加上/*    */注释3.要修改在eclispe中的命令的快捷键方式我们只 ...

  7. mac OS X下git代码行统计命令

    1.统计某人的代码提交量,包括增加,删除 git log --author=-- --until=-- --pretty=tformat: --numstat | awk '{ add += $1 ; ...

  8. 为什么要用ajax

    Ajax应用程序的优势在于:1. 通过异步模式,提升了用户体验2. 优化了浏览器和服务器之间的传输,减少不必要的数据往返,减少了带宽占用3. Ajax引擎在客户端运行,承担了一部分本来由服务器承担的工 ...

  9. jQuery之$(document).ready()使用介绍

    学习jQuery的第一件事是:如果你想要一个事件运行在你的页面上,你必须在$(document).ready()里调用这个事件 学习jQuery的第一件事是:如果你想要一个事件运行在你的页面上,你必须 ...

  10. Crusher Django 学习笔记1 hello world

    http://crusher-milling.blogspot.com/2013/09/crusher-django-tutorial1-hello-world.html 随便学习一下goagent ...