线段树.docx

上传人:b****1 文档编号:20130998 上传时间:2023-04-25 格式:DOCX 页数:25 大小:24.50KB
下载 相关 举报
线段树.docx_第1页
第1页 / 共25页
线段树.docx_第2页
第2页 / 共25页
线段树.docx_第3页
第3页 / 共25页
线段树.docx_第4页
第4页 / 共25页
线段树.docx_第5页
第5页 / 共25页
点击查看更多>>
下载资源
资源描述

线段树.docx

《线段树.docx》由会员分享,可在线阅读,更多相关《线段树.docx(25页珍藏版)》请在冰豆网上搜索。

线段树.docx

线段树

单点更新:

最最基础的线段树,只更新叶子节点,然后把信息用PushUP(intr)这个函数更新上来

∙hdu1166敌兵布阵

∙题意:

O(-1)

∙思路:

O(-1)

线段树功能:

update:

单点增减query:

区间求和

1.#include  

2.#include  

3.  

4.#define M 50005  

5.#define lson l,m,rt<<1  

6.#define rson m+1,r,rt<<1|1  

7./*left,right,root,middle*/  

8.  

9.int sum[M<<2];  

10.  

11.inline void PushPlus(int rt)  

12.{  

13.    sum[rt] = sum[rt<<1] + sum[rt<<1|1];  

14.}  

15.  

16.void Build(int l, int r, int rt)  

17.{  

18.    if(l == r)  

19.    {  

20.        scanf("%d", &sum[rt]);  

21.        return ;  

22.    }  

23.    int m = ( l + r )>>1;  

24.  

25.    Build(lson);  

26.    Build(rson);  

27.    PushPlus(rt);  

28.}  

29.  

30.void Updata(int p, int add, int l, int r, int rt)  

31.{  

32.  

33.    if( l == r )  

34.    {  

35.        sum[rt] += add;  

36.        return ;  

37.    }  

38.    int m = ( l + r ) >> 1;  

39.    if(p <= m)  

40.        Updata(p, add, lson);  

41.    else  

42.        Updata(p, add, rson);  

43.  

44.    PushPlus(rt);  

45.}  

46.  

47.int Query(int L,int R,int l,int r,int rt)  

48.{  

49.    if( L <= l && r <= R )  

50.    {  

51.        return sum[rt];  

52.    }  

53.    int m = ( l + r ) >> 1;  

54.    int ans=0;  

55.    if(L<=m )  

56.        ans+=Query(L,R,lson);  

57.    if(R>m)  

58.        ans+=Query(L,R,rson);  

59.  

60.    return ans;  

61.}  

62.int main()  

63.{     

64.    int T, n, a, b;  

65.    scanf("%d",&T);  

66.    for( int i = 1; i <= T; ++i )  

67.    {  

68.        printf("Case %d:

\n",i);  

69.        scanf("%d",&n);  

70.        Build(1,n,1);  

71.  

72.        char op[10];  

73.  

74.        while( scanf("%s",op) &&op[0]!

='E' )  

75.        {  

76.  

77.            scanf("%d %d", &a, &b);  

78.            if(op[0] == 'Q')  

79.                printf("%d\n",Query(a,b,1,n,1));  

80.            else if(op[0] == 'S')  

81.                Updata(a,-b,1,n,1);  

82.            else  

83.                Updata(a,b,1,n,1);  

84.  

85.        }  

86.    }  

87.    return 0;  

88.}  

hdu1754IHateIt

题意:

O(-1)

思路:

O(-1)

线段树功能:

update:

单点替换query:

区间最值

[cpp] viewplain copy

 print?

1.#include   

2.#include   

3.using namespace std;  

4.   

5.#define lson l , m , rt << 1  

6.#define rson m + 1 , r , rt << 1 | 1  

7.const int maxn = 222222;  

8.int MAX[maxn<<2];  

9.void PushUP(int rt) {  

10.    MAX[rt] = max(MAX[rt<<1] , MAX[rt<<1|1]);  

11.}  

12.void build(int l,int r,int rt) {  

13.    if (l == r) {  

14.        scanf("%d",&MAX[rt]);  

15.        return ;  

16.    }  

17.    int m = (l + r) >> 1;  

18.    build(lson);  

19.    build(rson);  

20.    PushUP(rt);  

21.}  

22.void update(int p,int sc,int l,int r,int rt) {  

23.    if (l == r) {  

24.        MAX[rt] = sc;  

25.        return ;  

26.    }  

27.    int m = (l + r) >> 1;  

28.    if (p <= m) update(p , sc , lson);  

29.    else update(p , sc , rson);  

30.    PushUP(rt);  

31.}  

32.int query(int L,int R,int l,int r,int rt) {  

33.    if (L <= l && r <= R) {  

34.        return MAX[rt];  

35.    }  

36.    int m = (l + r) >> 1;  

37.    int ret = 0;  

38.    if (L <= m) ret = max(ret , query(L , R , lson));  

39.    if (R > m) ret = max(ret , query(L , R , rson));  

40.    return ret;  

41.}  

42.int main() {  

43.    int n , m;  

44.    while (~scanf("%d%d",&n,&m)) {  

45.        build(1 , n , 1);  

46.        while (m --) {  

47.            char op[2];  

48.            int a , b;  

49.            scanf("%s%d%d",op,&a,&b);  

50.            if (op[0] == 'Q') printf("%d\n",query(a , b , 1 , n , 1));  

51.            else update(a , b , 1 , n , 1);  

52.        }  

53.    }  

54.    return 0;  

55.}  

hdu1394MinimumInversionNumber

如2431中,21,43,41,31是逆序,逆序数是4,为偶排列。

题意:

求Inversion后的最小逆序数

思路:

用O(nlogn)复杂度求出最初逆序数后,就可以用O

(1)的复杂度分别递推出其他解

线段树功能:

update:

单点增减query:

区间求和

[cpp] viewplain copy

 print?

1.#include   

2.#include   

3.using namespace std;  

4.   

5.#define lson l , m , rt << 1  

6.#define rson m + 1 , r , rt << 1 | 1  

7.const int maxn = 5555;  

8.int sum[maxn<<2];  

9.void PushUP(int rt) {  

10.    sum[rt] = sum[rt<<1] + sum[rt<<1|1];  

11.}  

12.void build(int l,int r,int rt) {  

13.    sum[rt] = 0;  

14.    if (l == r) return ;  

15.    int m = (l + r) >> 1;  

16.    build(lson);  

17.    build(rson);  

18.}  

19.void update(int p,int l,int r,int rt) {  

20.    if (l == r) {  

21.        sum[rt] ++;  

22.        return ;  

23.    }  

24.    int m = (l + r) >> 1;  

25.    if (p <= m) update(p , lson);  

26.    else update(p , rson);  

27.    PushUP(rt);  

28.}  

29.int query(int L,int R,int l,int r,int rt) {  

30.    if (L <= l && r <= R) {  

31.        return sum[rt];  

32.    }  

33.    int m = (l + r) >> 1;  

34.    int ret = 0;  

35.    if (L <= m) ret += query(L , R , lson);  

36.    if (R > m) ret += query(L , R , rson);  

37.    return ret;  

38.}  

39.int x[maxn];  

40.int main() {  

41.    int n;  

42.    while (~scanf("%d",&n)) {  

43.        build(0 , n - 1 , 1);  

44.        int sum = 0;  

45.        for (int i = 0 ; i < n ; i ++) {  

46.            scanf("%d",&x[i]);  

47.            sum += query(x[i] , n - 1 , 0 , n - 1 , 1);  

48.            update(x[i] , 0 , n - 1 , 1);  

49.        }  

50.        int ret = sum;  

51.        for (int i = 0 ; i < n ; i ++) {  

52.            sum += n - x[i] - x[i] - 1;  

53.            ret = min(ret , sum);  

54.        }  

55.        printf("%d\n",ret);  

56.    }  

57.    return 0;  

58.}  

hdu2795Billboard

题意:

h*w的木板,放进一些1*L的物品,求每次放空间能容纳且最上边的位子

思路:

每次找到最大值的位子,然后减去L

线段树功能:

query:

区间求最大值的位子(直接把update的操作在query里做了)

[cpp] viewplain copy

 print?

用数的最下面的节点表示一层(即到最下面一层有n个节点就可以了),并且用这个节点的左或右的区间范围表示层数(子节点的左区间和右区间其实是相同的),这个思路很巧,我也是看了别人的题解才懂的

1.#include   

2.#include   

3.using namespace std;  

4.   

5.#define lson l , m , rt << 1  

6.#define rson m + 1 , r , rt << 1 | 1  

7.const int maxn = 222222;  

8.int h , w , n;  

9.int MAX[maxn<<2];  

10.void PushUP(int rt) {  

11.    MAX[rt] = max(MAX[rt<<1] , MAX[rt<<1|1]);  

12.}  

13.void build(int l,int r,int rt) {  

14.    MAX[rt] = w;  

15.    if (l == r) return ;  

16.    int m = (l + r) >> 1;  

17.    build(lson);  

18.    build(rson);  

19.}  

20.int query(int x,int l,int r,int rt) {  

21.    if (l == r) {  

22.        MAX[rt] -= x;  

23.        return l;  

24.    }  

25.    int m = (l + r) >> 1;  

26.    int ret = (MAX[rt<<1] >= x) ?

 query(x , lson) :

 query(x , rson);  

27.    PushUP(rt);  

28.    return ret;  

29.}  

30.int main() {  

31.    while (~scanf("%d%d%d",&h,&w,&n)) {  

32.        if (h > n) h = n;  

33.        build(1 , h , 1);  

34.        while (n --) {  

35.            int x;  

36.            scanf("%d",&x);  

37.            if (MAX[1] < x) puts("-1");  

38.            else printf("%d\n",query(x , 1 , h , 1));  

39.        }  

40.    }  

41.    return 0;  

42.}  

成段更新(通常这对初学者来说是一道坎),需要用到延迟标记(或者说懒惰标记),简单来说就是每次更新的时候不要更新到底,用延迟标记使得更新延迟到下次需要更新or询问到的时候

hdu1698JustaHook

题意:

O(-1)

思路:

O(-1)

线段树功能:

update:

成段替换(由于只query一次总区间,所以可以直接输出1结点的信息)

[cpp] viewplain copy

 print?

1.#include   

2.#include   

3.using namespace std;  

4.   

5.#define lson l , m , rt << 1  

6.#define rson m + 1 , r , rt << 1 | 1  

7.const int maxn = 111111;  

8.int h , w , n;  

9.int col[maxn<<2];  

10.int sum[maxn<<2];  

11.void PushUp(int rt) {  

12.    sum[rt] = sum[rt<<1] + sum[rt<<1|1];  

13.}  

14.void PushDown(int rt,int m) {  

15.    if (col[rt]) {  

16.        col[rt<<1] = col[rt<<1|1] = col[rt];  

17.        sum[rt<<1] = (m - (m >> 1)) * col[rt];  

18.        sum[rt<<1|1] = (m >> 1) * col[rt];  

19.        col[rt] = 0;  

20.    }  

21.}  

22.void build(int l,int r,int rt) {  

23.    col[rt] = 0;  

24.    sum[rt] = 1;  

25.    if (l == r) return ;  

26.    int m = (l + r) >> 1;  

27.    build(lson);  

28.    build(rson);  

29.    PushUp(rt);  

30.}  

31.void update(int L,int R,int c,int l,int r,int rt) {  

32.    if (L <= l && r <= R) {  

33.        col[rt] = c;  

34.        sum[rt] = c * (r - l + 1);  

35.        return ;  

36.    }  

37.    PushDown(rt , r - l + 1);  

38.    int m = (l + r) >> 1;  

39.    if (L <= m) update(L , R , c , lson);  

40.    if (R > m) update(L , R , c , rson);  

41.    PushUp(rt);  

42.}  

43.int main() {  

44.    int T , n , m;  

45.    scanf("%d",&T);  

46.    for (int cas = 1 ; cas <= T ; cas ++) {  

47.        scanf("%d%d",&n,&m);  

48.        build(1 , n , 1);  

49.        while (m --) {  

50.            int a , b , c;  

51.            scanf("%d%d%d",&a,&b,&c);  

52.            update(a , b , c , 1 , n , 1);  

53.        }  

54.        printf("Case %d:

 The total value of the hook is %d.\n",cas , sum[1]);  

55.    }  

56.    return 0;  

57.}  

poj3468ASimpleProblemwithIntegers

题意:

O(-1)

思路:

O(-1)

线段树功能:

update:

成段增减query:

区间求和

[cpp] viewplain copy

 print?

1.#include   

2.#include   

3.using namespace std;  

4.   

5.#define lson l , m , rt << 1  

6.#define rson m + 1 , r , rt << 1 | 1  

7.#define LL long long  

8.const int maxn = 111111;  

9.LL add[maxn<<2];  

10.LL sum[maxn<<2];  

11.void PushUp(int rt) {  

12.    sum[rt] = sum[rt<<1] + sum[rt<<1|1];  

13.}  

14.void PushDown(int rt,int m) {  

15.    if (add[rt]) {  

16.        add[rt<<1] += add[rt];  

17.        add[rt<<1|1] += add[rt];  

18.        sum[rt<<1] += add[rt] * (m - (m >> 1));  

19.        sum[rt<<1|1] += add[rt] * (m >> 1);  

20.     

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 高等教育 > 历史学

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1