数据结构习题 线段树&树状数组
说明:这是去年写了一半的东西,一直存在草稿箱里,今天整理东西的时候才发现,还是把它发表出来吧。。
以下所有题目来自Lrj的《训练指南》
LA 2191
单点修改,区间和 Fenwick直接搞
UVa 12299
给出n个数,支持循环移动某些数(<30个),然后问区间最小值
因为移动小于30个数,所以直接单点修改就行,线段树。
LA 4108
类似线段树,每次插入一个建筑时想线段树一样二分区间,当遇到一个完整的区间时,修改或返回,否则继续二分区间。Nlogn.
UVa 11525
有题解说可以逆向考虑用线段树,我没明白怎么回事。
说一下我的做法:
考虑问题(k,n)表示1~k的全排列中第n个。显然1~k的全排列可以分为k种,每种有(k-1)!种情况,那么如果确定了第n个排列属于哪一种,问题就转化为了(k-1,m);
再考虑题目的输入。N的输入形式正好是按以上思想给出的,那么我们是需要把这个式子转化为标准形式即可。
判断每个Si,若Si>(k-i+1),就要”进位”。所以从后向前扫描,可以在O(n)时间内解决。
LA 4730
并查集+线段树。用并查集维护每个州,同时维护每个州的上端点(up)和下端点(down)。
用线段树维护[a,b]内有多少个城市。方法是连接A和B时,[A.down,A.up]-=A.count; [B.down,B.up]-=B.count; [new.down,new.up]+=new.count;
二维线段树
先存一下(以下代码仅供参考 准确性无法保证233)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <cstdio> 2 #include <cstdlib> 3 #include <iostream> 4 #include <cstring> 5 #define RS(x) (x*2+1) 6 #define LS(x) (x*2) 7 #define bigger(a,b) ((a)>(b)?(a):(b)) 8 #define minner(a,b) ((a)<(b)?(a):(b)) 9 #define MAXN (2000+10) 10 #define root (1) 11 #define INF (9999999) 12 using namespace std; 13 struct Segment_Tree_2D{ 14 struct treeY{ 15 int max,min; 16 int L,R; 17 int mid; 18 }; 19 typedef struct treeY treeY; 20 struct treeX{ 21 treeY T[MAXN]; 22 int L,R; 23 int mid; 24 }; 25 typedef struct treeX treeX; 26 int x1,x2,y1,y2,val,max_ans,min_ans,x0,y0; 27 treeX t[MAXN]; 28 void queryY(int f,int r,int fa,int p){//ok 29 if (r>t[fa].T[p].R) r=t[fa].T[p].R; 30 if (f<t[fa].T[p].L) f=t[fa].T[p].L; 31 if (f==t[fa].T[p].L&&r==t[fa].T[p].R){ 32 max_ans=bigger(max_ans,t[fa].T[p].max); 33 min_ans=minner(min_ans,t[fa].T[p].min); 34 }else{ 35 int mid=t[fa].T[p].mid; 36 if (r>mid) queryY(mid+1,r,fa,RS(p)); 37 if (f<=mid) queryY(f,mid,fa,LS(p)); 38 } 39 } 40 void queryX(int f,int r,int p){//ok 41 if (r>t[p].R) r=t[p].R; 42 if (f<t[p].L) f=t[p].L; 43 if (f==t[p].L&&r==t[p].R){ 44 queryY(y1,y2,p,root); 45 }else{ 46 int mid=t[p].mid; 47 if (r>mid) queryX(mid+1,r,RS(p)); 48 if (f<=mid) queryX(f,mid,LS(p)); 49 } 50 } 51 void modifyY(int fa,int p){//ok 52 if (y0==t[fa].T[p].L&&y0==t[fa].T[p].R){ 53 t[fa].T[p].min=val; 54 t[fa].T[p].max=val; 55 }else{ 56 int mid=t[fa].T[p].mid; 57 if (y0>mid) modifyY(fa,RS(p)); 58 if (y0<=mid) modifyY(fa,LS(p)); 59 } 60 t[fa].T[p].max=bigger(t[fa].T[LS(p)].max,t[fa].T[RS(p)].max); 61 t[fa].T[p].min=minner(t[fa].T[LS(p)].min,t[fa].T[RS(p)].min); 62 } 63 void maintainY(int fa,int p){//ok 64 if (y0==t[fa].T[p].L&&y0==t[fa].T[p].R){ 65 t[fa].T[p].min=minner(t[LS(fa)].T[p].min,t[RS(fa)].T[p].min); 66 t[fa].T[p].max=bigger(t[LS(fa)].T[p].max,t[RS(fa)].T[p].max); 67 }else{ 68 int mid=t[fa].T[p].mid; 69 if (y0>mid) maintainY(fa,RS(p)); 70 if (y0<=mid) maintainY(fa,LS(p)); 71 } 72 t[fa].T[p].max=bigger(t[fa].T[LS(p)].max,t[fa].T[RS(p)].max); 73 t[fa].T[p].min=minner(t[fa].T[LS(p)].min,t[fa].T[RS(p)].min); 74 } 75 void modifyX(int p){ 76 if (x0==t[p].L&&x0==t[p].R){ 77 modifyY(p,root); 78 }else{ 79 int mid=t[p].mid; 80 if (x0>mid) modifyX(RS(p)); 81 if (x0<=mid) modifyX(LS(p)); 82 maintainY(p,root); 83 } 84 } 85 86 void query(){max_ans=-INF;min_ans=INF;queryX(x1,x2,root);} 87 void modify(){modifyX(root);} 88 }; 89 typedef struct Segment_Tree_2D ST2; 90 ST2 t; 91 int main() 92 { 93 int i,j,n,m,temp,q; 94 char cmd[10]; 95 scanf("%d%d",&n,&m); 96 for (i=1;i<=n;i++){ 97 for (j=1;j<=m;j++){ 98 scanf("%d",&temp); 99 t.x0=i; t.y0=j; 100 t.modify(); 101 } 102 } 103 scanf("%d",&q); 104 for (i=0;i<q;i++){ 105 scanf("%s",cmd); 106 if (cmd[0]=='q'){ 107 scanf("%d%d%d%d",&t.x1,&t.y1,&t.x2,&t.y2); 108 t.query(); 109 printf("%d %d\n",t.max_ans,t.min_ans); 110 }else{ 111 scanf("%d%d",&t.x0,&t.y0); 112 t.modify(); 113 } 114 } 115 return 0; 116 }
wsc500原创,转载请注明出处。请注明 出自http://www.cnblogs.com/loveidea/