线段数:
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; }