线段数:
http://dongxicheng.org/structure/segment-tree/
http://hi.baidu.com/semluhiigubbqvq/item/be736a33a8864789f4e4ad18
http://www.notonlysuccess.com/index.php/segment-tree-complete/ 经典
单点更新:
hdu1166
#include<stdio.h>
#define MAXN 50000
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
int sum[MAXN<<2];
//maxn的取值 2^0+2^1+...+2^k(x^k>=n)=2^(k+1)-1>=maxn;
bool cmp(int x,int y)
{
return x<y;
}
//向上
void PushUp(int rt)
{
sum[rt]=sum[rt<<1]+sum[rt<<1|1];
}
//建树,由子节点确定根节点
void build(int l,int r,int rt)
{
if(l==r)
{
scanf("%d",&sum[rt]);
return ;
}
int m=(r+l)>>1;
build(lson);
build(rson);
PushUp(rt);
}
//更新一个点,由子节点确定根节点
void update(int p,int add,int l,int r,int rt)
{
//如果l==r,更新单点
if(l==r)
{
sum[rt]+=add;
return ;
}
//找p所在的范围
int m=(l+r)>>1;
if(m>=p) update(p,add,lson);
else update(p,add,rson);
PushUp(rt);
}
//询问,将所询问的断分成很多区间的和
int query(int L,int R,int l,int r,int rt)
{
//l,r在所询问的范围内,则返回该段和
if(L<=l&&r<=R)
{
return sum[rt];
}
int m=(l+r)>>1;
int ret=0;
//
if(R>m)
ret+=query(L,R,rson);
if(L<=m)
ret+=query(L,R,lson);
return ret;
}
int main()
{
int T,N,i;
scanf("%d",&T);
for(i=0; i<T; i++)
{
printf("Case %d:\n",i+1);
scanf("%d",&N);
build(1,N,1);
char s[20];
int a,b;
while(scanf("%s",s)!=EOF)
{
if(s[0]=='E') break;
scanf("%d%d",&a,&b);
if(s[0]=='A')
{
update(a,b,1,N,1);
}
else if(s[0]=='S')
{
update(a,-b,1,N,1);
}
else
{
printf("%d\n",query(a,b,1,N,1));
}
}
}
return 0;
}
#include<stdio.h>
#define maxn 5555
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
int sum[maxn<<2];
int aa[maxn];
int min(int a,int b)
{
return a>b?b:a;
}
//向上更新
void PushUp(int rt)
{
sum[rt]=sum[rt<<1]+sum[rt<<1|1];
}
//建树
void build(int l,int r,int rt)
{
sum[rt]=0;
if(l==r)
{
return ;
}
int m=(l+r)>>1;
build(lson);
build(rson);
}
//更新
void update(int a,int l,int r,int rt)
{
if(l==r)
{
sum[rt]++;
return ;
}
int m=(l+r)>>1;
if(a<=m)
update(a,lson);
else
update(a,rson);
PushUp(rt);
}
//询问L到r共有多少个数
int query(int L,int R,int l,int r,int rt)
{
if(L<=l&&r<=R)
{
return sum[rt];
}
int ret=0;
int m=(l+r)>>1;
if(L<=m)
ret+=query(L,R,lson);
if(R>m)
ret+=query(L,R,rson);
return ret;
}
int main()
{
int n;
while(scanf("%d",&n)!=EOF)
//建立空树
{
build(0,n-1,1);
int sum0=0;
for(int i=0; i<n; ++i)
{
scanf("%d",&aa[i]);
//询问线段树中比a[i]大的数的个数;
sum0+=query(aa[i]+1,n-1,0,n-1,1);
//更新,插入a[i]这个点
update(aa[i],0,n-1,1);
}
int ans=sum0;
for(int i=0; i<n; ++i)
{
//将a[i]放到最后的逆序数,i从0到n-1
//每次移动时,a[i]为第一个数,比a[i]小的数有a[i]个,比a[i]大的数有n-a[i]-1个;
sum0=sum0-aa[i]+(n-aa[i]-1);
ans=min(ans,sum0);
}
printf("%d\n",ans);
}
return 0;
}
#include<stdio.h>
#define maxn 200005
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
int w;
int max[maxn<<2];
void PushUp(int rt)
{
max[rt]=max[rt<<1]>max[rt<<1|1]?max[rt<<1]:max[rt<<1|1];
}
//建树,每个节点的值都为w
void build(int l,int r,int rt)
{
max[rt]=w;
if(l==r) return ;
int m=(l+r)>>1;
build(lson);
build(rson);
}
//询问加更新。从最小的节点询问能否可以减掉x,并返回x所放的位置
int query(int x,int l,int r,int rt)
{
if(l==r)
{
max[rt]-=x;
return l;//返回x所放的位置
}
int m=(l+r)>>1;
int ret;
if(max[rt<<1]>=x)
ret=query(x,lson);//返回x所放的位置
else
ret=query(x,rson);//返回x所放的位置
PushUp(rt);
return ret;//返回x所放的位置
}
int main()
{
int h,n,x;
while(scanf("%d%d%d",&h,&w,&n)!=EOF)
{
if(h>n)
h=n;
//建树,以1-h为区间长,w为每个节点的长度
build(1,h,1);
while(n--)
{
scanf("%d",&x);
//从区间1-h询问每个节点是否能减掉x,如果可以滴话,更新树并输出
//利用最大堆的性质
if(max[1]<x)
printf("-1\n");
else
printf("%d\n",query(x,1,h,1));
}
}
return 0;
}