zoukankan      html  css  js  c++  java
  • 简单线段树中的一系列题目

    1.HDU 1166  http://acm.hdu.edu.cn/showproblem.php?pid=1166

    题目大意:
    了解地方的兵营人数,每次询问告知区间内的总人数,其中会有兵营人数变更的更新操作

    这里要用到求和的query:

    int query(int x,int y)
    {

        int
    i=D+x-1,j=D+y+1,ans=0;
        for
    (;i^j^1;i>>=1,j>>=1){
            if
    (~i&1) ans+=tree[i^1];
            if
    (j&1) ans+=tree[j^1];
        }

        return
    ans;
    }

    代码如下:

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cstring>
     4 #include <string>
     5 using namespace std;
     6 
     7 #define N 50005
     8 
     9 int a[N],tree[200010];
    10 int D;
    11 string s;
    12 
    13 void update(int x)
    14 {
    15     for(int i=x;i^1;i>>=1){
    16         tree[i>>1]=tree[i]+tree[i^1];
    17     }
    18 }
    19 
    20 int query(int x,int y)
    21 {
    22     int i=D+x-1,j=D+y+1,ans=0;
    23     for(;i^j^1;i>>=1,j>>=1){
    24         if(~i&1) ans+=tree[i^1];
    25         if(j&1) ans+=tree[j^1];
    26     }
    27     return ans;
    28 }
    29 int main()
    30 {
    31     int T,n,c,d;
    32     cin>>T;
    33     for(int i=1;i<=T;i++){
    34         D=1;
    35         memset(tree,0,sizeof(tree));
    36         scanf("%d",&n);
    37         for(int j=1;j<=n;j++) scanf("%d",&a[j]);
    38         while(D<n+2) D<<=1;
    39         for(int j=1;j<=n;j++) tree[D+j]=a[j];
    40         for(int j=D-1;j>=1;j--) tree[j]=tree[j<<1]+tree[j<<1|1];
    41         printf("Case %d:
    ",i);
    42         while(cin>>s){
    43             if(s=="End") break;
    44 
    45             else if(s=="Add"){
    46                 scanf("%d%d",&c,&d);
    47                 tree[D+c]+=d;
    48                 update(D+c);
    49             }
    50             else if(s=="Sub"){
    51                 scanf("%d%d",&c,&d);
    52                 tree[D+c]-=d;
    53                 update(D+c);
    54             }
    55             else if(s=="Query"){
    56                 scanf("%d%d",&c,&d);
    57                 printf("%d
    ",query(c,d));
    58             }
    59         }
    60     }
    61     return 0;
    62 }
    View Code

    2.HDU 1754 http://acm.hdu.edu.cn/showproblem.php?pid=1754

    题目大意:
    老师想要知道某段学生区间的最高分,中间涉及学生成绩的更新操作。

    这里用到的是求最大值的query:
    int query(int x,int y)
    {

        int
    i=D+x-1,j=D+y+1,ans=-1;
        for
    (;i^j^1;i>>=1,j>>=1){
            if
    (~i&1) ans=max(ans,tree[i^1]);
            if
    (j&1)  ans=max(ans,tree[j^1]);
        }

        return
    ans;
    }

    总代码如下:

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    #define N 200010
    int a[N],tree[4*N],D;
    
    void init()
    {
        D=1;
        memset(tree,-1,sizeof(tree));
    }
    void treeBuild()
    {
        for(int i=D-1;i>=1;i--)
            tree[i]=max(tree[i<<1],tree[(i<<1)^1]);
    }
    void update(int i)
    {
        for(;i^1;i>>=1){
            tree[i>>1]=max(tree[i],tree[i^1]);
        }
    }
    int query(int x,int y)
    {
        int i=D+x-1,j=D+y+1,ans=-1;
        for(;i^j^1;i>>=1,j>>=1){
            if(~i&1) ans=max(ans,tree[i^1]);
            if(j&1)  ans=max(ans,tree[j^1]);
        }
        return ans;
    }
    int main()
    {
        int n,m,x,y;
        char c;
        while(scanf("%d%d",&n,&m)!=EOF){
            init();
            while(D<n+2) D<<=1;
            for(int i=1;i<=n;i++){
                scanf("%d",&a[i]);
                tree[D+i]=a[i];
            }
            treeBuild();
            for(int i=1;i<=m;i++)
            {
                cin>>c;
                if(c=='U'){
                    scanf("%d%d",&x,&y);
                    tree[D+x]=y,update(D+x);
                }
                else if(c=='Q'){
                    scanf("%d%d",&x,&y);
                    printf("%d
    ",query(x,y));
                }
            }
        }
        return 0;
    }
    View Code

    3.HDU 2795 http://acm.hdu.edu.cn/showproblem.php?pid=2795
    题目大意:
    不断将广告靠上,再靠左贴,问能够贴到的行数

    这里我们在线段树上存储的是行的位置,用w[]数组存储每行还能存多少长度的广告

    这里虽说高度能达到10^9,但是我们在规划线段树的长度时并不需要那么长,因为n最大为200000,我们规划线段树的底层取到的是min(n,h);

    所以整棵树最大达到4*n即可

    这里不断将能够达到最大值的位置放在树顶,

    判断时不断往下,因为要贴广告时尽可能朝上,所以如果满足往左走,不满足往右走

    query

    int query(int k)
    {

        int
    t=1;
        if
    (w[tree[t]]<k) return -1; while(t<D){ if(w[tree[t<<1]]>=k) t<<=1;
            else
    t=t<<1|1;
        }

        return
    t-D;
    }

    总代码如下:

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    #define N 200010
    int w[N],tree[4*N],D,h,m,n,x,Min;
    
    void update(int i)
    {
        for(;i^1;i>>=1)
            tree[i>>1]=w[tree[i]]>w[tree[i^1]]?tree[i]:tree[i^1];
    }
    
    int query(int k)
    {
        int t=1;
        if(w[tree[t]]<k) return -1;
        while(t<D){
            if(w[tree[t<<1]]>=k) t<<=1;
            else t=t<<1|1;
        }
        return t-D;
    }
    
    int main()
    {
        while(scanf("%d%d%d",&h,&m,&n)!=EOF){
            Min=min(h,n);
            memset(tree,0,sizeof(tree));
            w[0]=0;
            for(D=1;D<Min+2;D<<=1);
            for(int i=1;i<=Min;i++) w[i]=m,tree[D+i]=i;
            for(int i=D-1;i>=1;i--) tree[i]=w[tree[i<<1]]>w[tree[i<<1|1]]?tree[i<<1]:tree[i<<1|1];
            for(int i=1;i<=n;i++){
                scanf("%d",&x);
                int t=query(x);
                printf("%d
    ",t);
                w[t]-=x,update(D+t);
            }
        }
        return 0;
    }
    View Code
  • 相关阅读:
    个人工作总结6
    使用java对文件批量重命名
    导入csv文件到数据库
    关于微信小程序的Request请求错误处理
    基于jPlayer的三分屏制作
    条件查询时,如果有的输入框不输入,后台应该怎么处理?
    mysql 1449 : The user specified as a definer ('root'@'%') does not exist 解决方法
    C++&&Objective-c
    加载ttf字体
    ios6去除高光效果,和判断iphone或ipad设备
  • 原文地址:https://www.cnblogs.com/CSU3901130321/p/3877993.html
Copyright © 2011-2022 走看看