8.8线段树和树状数组
题目链接 http://acm.hust.edu.cn/vjudge/contest/view.action?cid=28619#overview
密码 acmore
还是感觉不怎么会线段树,还是得给自己另外多找点题目练练
Problem A HDU 3874
树状数组+离线操作见http://www.cnblogs.com/gj-Acit/p/3249827.html
Problem B HDU 2227
Find the nondecreasing subsequences
见http://www.cnblogs.com/gj-Acit/p/3258508.html
Problem C HDU 1541
题目意思是说给出一些星星的坐标,他们每个星星的等级是按照每个星星左下方星星的数目来定的,即所有点中满足x<x0,y<y0的点的数目就是这个店的等级。求每个等级的星星有多少个。
由于题目给出的坐标中y是按照升序给出的,所以我们只需要每输入一个坐标,就先查询它的x坐标的前方有多少个点,再将这个点插入到坐标轴中去,这样的话就可以保证每次查询的都是当前点的左下方的点的数目。这样的话就可以用树状数组来记录从1~x的区间内有多少个已经被标记的点。
1 #include <stdio.h> 2 #include <string.h> 3 #define mem(a) memset(a,0,sizeof(a)) 4 #define MAX(a , b) ((a) > (b) ? (a) : (b)) 5 6 int TreeArray[32005], N; 7 int ans[32005]; 8 int X[15005], Y; 9 10 int LowBit(int x) 11 { 12 return x&(-x); 13 } 14 15 int GetSum(int k)//返回区间1~k有多少个点 16 { 17 int sum = 0; 18 while(k>=1) 19 { 20 sum += TreeArray[k]; 21 k -= LowBit(k); 22 } 23 return sum; 24 } 25 26 void Edit(int k,int Len)//插入一个点 27 { 28 while(k<=Len) 29 { 30 TreeArray[k] += 1; 31 k += LowBit(k); 32 } 33 } 34 35 int main() 36 { 37 while(~scanf("%d", &N)) 38 { 39 mem(ans); mem(TreeArray); 40 mem(X); 41 int Max = 0; 42 for(int i=1;i<=N;i++) 43 { 44 scanf("%d%d", &X[i], &Y);//其实不用吧每个点记录下来,可以每次都直接在区间1~32000内查找 45 X[i]+=1;//由于题目说x有可能为0,而树状数组不可以记录点0,所以全部的x都+1 46 Max = MAX(X[i], Max);//我是想要找出区间最大坐标,然后在1到最大区间内查询 47 } 48 for(int i=1;i<=N;i++) 49 { 50 ans[GetSum(X[i])]++;//先查询 51 Edit(X[i], Max);//后把点插入到坐标中去 52 } 53 for(int i=0;i<N;i++) 54 { 55 printf("%d\n", ans[i]); 56 } 57 } 58 return 0; 59 }
Problem D HDU 1754
线段树的基本操作,区间查询和节点修改
虽然此题比较简单,但是有一点学到的就是代码风格,要学会尽量让代码清晰易懂
1 #include <stdio.h> 2 #include <string.h> 3 #define MAX(a, b) ((a) > (b) ? (a) : (b)) 4 #define mem(a) memset(a, 0, sizeof(a)) 5 #define lson k<<1, l, mid 6 #define rson k<<1|1, mid+1, r 7 #define MAXN 200005 8 9 int Max[MAXN<<2], N, M; 10 11 void edit(int k, int l,int r, int num, int v) 12 { 13 if(l == r) 14 { 15 Max[k] = v; 16 return ; 17 } 18 int mid = (l+r)>>1; 19 if(num <= mid)edit(lson, num, v); 20 else edit(rson, num, v); 21 Max[k] = MAX(Max[k<<1], Max[k<<1|1]); 22 } 23 24 int query(int k,int l,int r,int L,int R) 25 { 26 if(L<=l && r<=R)return Max[k]; 27 int mid = (l+r)>>1, Lans=0, Rans =0; 28 if(L <= mid) Lans = query(lson, L, R); 29 if(R > mid) Rans = query(rson, L, R); 30 return MAX(Lans, Rans); 31 } 32 33 int main() 34 { 35 while(~scanf("%d %d", &N, &M)) 36 { 37 int A, B; 38 char ch; mem(Max); 39 for(int i=1;i<=N;i++) 40 { 41 scanf("%d%*c", &A); 42 edit(1,1,N,i,A); 43 } 44 for(int i=0;i<M;i++) 45 { 46 scanf("%c %d %d%*c", &ch, &A, &B); 47 if(ch == 'Q') printf("%d\n", query(1,1,N,A,B)); 48 else edit(1,1,N,A,B); 49 } 50 } 51 return 0; 52 }
Problem E POJ 3264
一样都是基本操作
1 #include <stdio.h> 2 #include <string.h> 3 #define INF 1000010 4 #define mem(a) memset(a,0,sizeof(a)) 5 #define lson k<<1, l, mid 6 #define rson k<<1|1,mid+1, r 7 #define MAX(a,b) (a>b?a:b) 8 #define MIN(a,b) (a<b?a:b) 9 #define MAXN 50005 10 11 int minH[MAXN<<2], maxH[MAXN<<2]; 12 int N, M; 13 14 void init() 15 { 16 for(int i=0;i<=(N<<2);i++) 17 { 18 minH[i] = INF; 19 maxH[i] = -INF; 20 } 21 } 22 23 void edit(int k,int l,int r,int num, int val) 24 { 25 if(l==r){ 26 minH[k] = maxH[k] = val; 27 return ; 28 } 29 int mid = (l+r)>>1; 30 if(num <= mid) edit(lson, num, val); 31 else edit(rson,num,val); 32 minH[k] = MIN(minH[k<<1], minH[k<<1|1]); 33 maxH[k] = MAX(maxH[k<<1], maxH[k<<1|1]); 34 } 35 36 int query(int k,int l,int r,int L,int R,int IsMin) 37 { 38 if(L<=l && r<=R) return IsMin ? minH[k] : maxH[k]; 39 int mid = (l+r)>>1, Lval=INF, Rval=INF; 40 if(L <= mid) Lval = query(lson,L,R,IsMin); 41 if(R > mid) Rval = query(rson,L,R,IsMin); 42 if(IsMin) return MIN(Lval, Rval); 43 return MAX((Lval==INF?-INF:Lval), (Rval==INF?-INF:Rval)); 44 } 45 46 int main() 47 { 48 while(~scanf("%d%d", &N, &M)) 49 { 50 init(); int h; 51 for(int i=1;i<=N;i++) 52 { 53 scanf("%d", &h); 54 edit(1,1,N,i,h); 55 } 56 int A, B; 57 for(int i=0;i<M;i++) 58 { 59 scanf("%d %d", &A, &B); 60 printf("%d\n", query(1,1,N,A,B,0) - query(1,1,N,A,B,1)); 61 } 62 } 63 return 0; 64 }
Problem G POJ 2299