数据结构习题 线段树&树状数组

说明:这是去年写了一半的东西,一直存在草稿箱里,今天整理东西的时候才发现,还是把它发表出来吧。。


 

以下所有题目来自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)

View Code
  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 }

 

转载于:https://www.cnblogs.com/loveidea/p/2981703.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值