zoukankan      html  css  js  c++  java
  • HDU 1166

    题意

    给出n个敌兵阵营的人数,给出一些操作命令:
    (1) Add i j , 第i个营地增加j个人
    (2)Sub i j , 第i个营地减少j个人(j不超过30);
    (3)Query i j , 询问第i到第j个营地的总人数;
    (4)End 表示结束

    思路

    线段树模板题 /*单点覆盖,区间查询*/

    下面记录一下几个好用的线段树模板:

    /*单点覆盖,区间查询*/
    #include <cstdio>
    #include <algorithm>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    #define lson l , m , rt << 1
    #define rson m + 1 , r , rt << 1 | 1
    const int maxn = 100007;
    const int INF=0x7fffffff;
    int MAX[maxn<<2];
    int MIN[maxn<<2];
    int SUM[maxn<<2];
    void PushUP(int rt) {
        MAX[rt] = max(MAX[rt<<1] , MAX[rt<<1|1]);
        MIN[rt] = min(MIN[rt<<1] , MIN[rt<<1|1]);
        SUM[rt] = SUM[rt<<1] + SUM[rt<<1|1];
    }
    //所有的 l ,r ,rt 参数为 1,n, 1   其中n为区间长度
    void build(int l,int r,int rt) {   //建树
        if (l == r) {
            MAX[rt] = MIN[rt] =SUM[rt]=0;  //初始化线段树为0的写法
            /*
              //边读入边建树的写法,复杂度O(n)  若执行n次更新来初始化的话复杂度为O(nlogn)
                scanf("%d",&MAX[rt]);
                MIN[rt] = MAX[rt];
                SUM[rt] = MAX[rt];
            */
            return ;
        }
        int m = (l + r) >> 1;
        build(lson);
        build(rson);
        PushUP(rt);
    }
    void update(int p,int v,int l,int r,int rt) {  //单点替换,把p位置的值置为v
        if (l == r) {
            MAX[rt] = v;
            MIN[rt] = v;
            SUM[rt] = v;
            return ;
        }
        int m = (l + r) >> 1;
        if (p <= m) update(p , v ,lson);
        else update(p , v , rson);
        PushUP(rt);
    }
    void update1(int p,int addv,int l,int r,int rt) {  //单点增加,把p位置的值增加v
        if (l == r) {
            SUM[rt] = SUM[rt] + addv;
            MIN[rt] = MIN[rt] + addv;
            MAX[rt] =MAX[rt]+addv;
            return ;
        }
        int m = (l + r) >> 1;
        if (p <= m) update1(p , addv ,lson);
        else update1(p , addv , rson);
        PushUP(rt);
    }
    int queryMAX(int L,int R,int l,int r,int rt) {   //求L~R的最大值
        if (L <= l && r <= R) {
            return MAX[rt];
        }
        int m = (l + r) >> 1;
        int ret = -INF;
        if (L <= m) ret = max(ret , queryMAX(L , R , lson));
        if (R > m)  ret =  max(ret , queryMAX(L , R , rson));
        return ret;
    }
    int queryMIN(int L,int R,int l,int r,int rt) {  //求L~R的最小值
        if (L <= l && r <= R) {
            return MIN[rt];
        }
        int m = (l + r) >> 1;
        int ret = INF;
        if (L <= m) ret = min(ret , queryMIN(L , R , lson));
        if (R > m)  ret =  min(ret , queryMIN(L , R , rson));
        return ret;
    }
    int querySUM(int L,int R,int l,int r,int rt) {   //求L~R的和
        if (L <= l && r <= R) {
            return SUM[rt];
        }
        int m = (l + r) >> 1;
        int ret = 0;
        if (L <= m) ret += querySUM(L , R , lson);
        if (R > m)  ret +=  querySUM(L , R , rson);
        return ret;
    }
    int main() {
        int n , m;
        while (~scanf("%d%d",&n,&m)) {
            build(1 , n , 1);
            while (m --) {
                char op[2];
                int a , b;
                scanf("%s%d%d",op,&a,&b);
                if (op[0] == 'Q') { //区间求最大
                    printf("%d
    ",queryMAX(a , b , 1 , n , 1));
                } else if(op[0]=='U') //单点替换
                    update(a , b , 1 , n , 1);
                else if(op[0]=='M') { //区间求最小
                    printf("%d
    ",queryMIN(a , b , 1 , n , 1));
                } else if(op[0]=='H') { //区间求和
                    printf("%d
    ",querySUM(a , b , 1 , n , 1));
                } else if(op[0]=='S') { //单点增加
                    update1(a , b , 1 , n , 1);
                } else if(op[0]=='E') { //单点减少
                    update1(a , -b , 1 , n , 1);
                }
            }
        }
        return 0;
    }
    
    
    /* 区间覆盖,区间查询*/
    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <algorithm>
    
    #define max(a,b) (a>b)?a:b
    #define min(a,b) (a>b)?b:a
    #define lson l , m , rt << 1
    #define rson m + 1 , r , rt << 1 | 1
    const int maxn = 100100;
    const int INF=0x7fffffff;
    using namespace std;
    int lazy[maxn<<2];
    int MAX[maxn<<2];
    int MIN[maxn<<2];
    int SUM[maxn<<2];
    void PushUp(int rt) { //由左孩子、右孩子向上更新父节点
        SUM[rt] = SUM[rt<<1] + SUM[rt<<1|1];
        MAX[rt] = max(MAX[rt<<1],MAX[rt<<1|1]);
        MIN[rt] = min(MIN[rt<<1],MIN[rt<<1|1]);
    }
    void PushDown(int rt,int m) { //向下更新
        if (lazy[rt]) { //懒惰标记
            lazy[rt<<1] = lazy[rt<<1|1] = lazy[rt];
            SUM[rt<<1] = (m - (m >> 1)) * lazy[rt];
            SUM[rt<<1|1] = ((m >> 1)) * lazy[rt];
            MAX[rt<<1]=MAX[rt<<1|1]=lazy[rt];
            MIN[rt<<1]=MIN[rt<<1|1]=lazy[rt];
            lazy[rt] = 0;
        }
    }
    //所有的l,r,rt  带入1,n,1
    void build(int l,int r,int rt) { //初始化建树
        lazy[rt] = 0;
        if (l== r) {
            SUM[rt]=MAX[rt]=MIN[rt]=0;  //初始化为0的建树
            /*scanf("%d",&SUM[rt]);  //边读入边建树的方法
              MAX[rt]=MIN[rt]=SUM[rt];
            */
            return ;
        }
        int m = (l + r) >> 1;
        build(lson);
        build(rson);
        PushUp(rt);
    }
    void update(int L,int R,int v,int l,int r,int rt) { //将L~R区间的值置为v
        //if(L>l||R>r) return;
        if (L <= l && r <= R) {
            lazy[rt] = v;
            SUM[rt] = v * (r - l + 1);
            MIN[rt] = v;
            MAX[rt] = v;
            //printf("%d %d %d %d %d
    ", rt, sum[rt], c, l, r);
            return ;
        }
        PushDown(rt , r - l + 1);
        int m = (l + r) >> 1;
        if (L <= m) update(L , R , v , lson);
        if (R > m) update(L , R , v , rson);
        PushUp(rt);
    }
    
    int querySUM(int L,int R,int l,int r,int rt) {  //求区间L~R的和
        if (L <= l && r <= R) {
            //printf("%d
    ", sum[rt]);
            return SUM[rt];
        }
        PushDown(rt , r - l + 1);
        int m = (l + r) >> 1;
        int ret = 0;
        if (L <= m) ret += querySUM(L , R , lson);
        if (m < R) ret += querySUM(L , R , rson);
        return ret;
    }
    int queryMIN(int L,int R,int l,int r,int rt) {  //求区间L~R的最小值
        if (L <= l && r <= R) {
            //printf("%d
    ", sum[rt]);
            return MIN[rt];
        }
        PushDown(rt , r - l + 1);
        int m = (l + r) >> 1;
        int ret = INF;
        if (L <= m) ret = min(ret, queryMIN(L , R , lson));
        if (m < R) ret = min(ret,queryMIN(L , R , rson));
        return ret;
    }
    int queryMAX(int L,int R,int l,int r,int rt) {  //求区间L~R的最大值
        if (L <= l && r <= R) {
            //printf("%d
    ", sum[rt]);
            return MAX[rt];
        }
        PushDown(rt , r - l + 1);
        int m = (l + r) >> 1;
        int ret = -INF;
        if (L <= m) ret = max(ret, queryMAX(L , R , lson));
        if (m < R) ret = max(ret,queryMAX(L , R , rson));
        return ret;
    }
    
    int main() {
        int  n , m;
        char str[5];
        while(scanf("%d%d",&n,&m)) {
            build(1 , n , 1);
            while (m--) {
                scanf("%s",str);
                int a , b , c;
                if(str[0]=='T') {
                    scanf("%d%d%d",&a,&b,&c);
                    update(a , b , c , 1 , n , 1);
                } else if(str[0]=='Q') {
                    scanf("%d%d",&a,&b);
                    cout<<querySUM(a,b,1,n,1)<<endl;
                } else if(str[0]=='A') {
                    scanf("%d%d",&a,&b);
                    cout<<queryMAX(a,b,1,n,1)<<endl;
                } else if(str[0]=='I') {
                    scanf("%d%d",&a,&b);
                    cout<<queryMIN(a,b,1,n,1)<<endl;
                }
            }
        }
        return 0;
    }
    
    /* 区间增加,区间查询*/
    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <algorithm>
    #define max(a,b) (a>b)?a:b
    #define min(a,b) (a>b)?b:a
    #define lson l , m , rt << 1
    #define rson m + 1 , r , rt << 1 | 1
    const int maxn = 100100;
    const int INF=0x7fffffff;
    using namespace std;
    int lazy[maxn<<2];
    int SUM[maxn<<2],MAX[maxn<<2],MIN[maxn<<2];
    void putup(int rt) {
        SUM[rt] = SUM[rt<<1] + SUM[rt<<1|1];
        MAX[rt] =max(MAX[rt<<1],MAX[rt<<1|1]) ;
        MIN[rt] =min(MIN[rt<<1],MIN[rt<<1|1]);
    }
    void putdown(int rt,int m) {
        if (lazy[rt]) {
            lazy[rt<<1] += lazy[rt];
            lazy[rt<<1|1] += lazy[rt];
            SUM[rt<<1] += lazy[rt] * (m - (m >> 1));
            SUM[rt<<1|1] += lazy[rt] * (m >> 1);
            MAX[rt<<1]+=lazy[rt];
            MAX[rt<<1|1] +=lazy[rt];
            MIN[rt<<1]+=lazy[rt];
            MIN[rt<<1|1]+=lazy[rt];
            lazy[rt] = 0;
        }
    }
    //以下的 l,r,rt 都带入 1,n,1
    void build(int l,int r,int rt) {  //初始化建树
        lazy[rt] = 0;
        if (l == r) {
            //初始化树为0的写法
            SUM[rt]=MAX[rt]=MIN[rt]=0;
            /*  //边读入边建树的写法
            scanf("%d",&SUM[rt]);
            MAX[rt]=MIN[rt]=SUM[rt];
            */
            return ;
        }
        int m = (l + r) >> 1;
        build(lson);
        build(rson);
        putup(rt);
    }
    void update(int L,int R,int v,int l,int r,int rt) {  //将区间L~R的值增加v
        if (L <= l && r <= R) {
            lazy[rt] += v;
            SUM[rt] += v * (r - l + 1);
            MAX[rt]+=v;
            MIN[rt]+=v;
            return ;
        }
        putdown(rt , r - l + 1);
        int m = (l + r) >> 1;
        if (L <= m) update(L , R , v , lson);
        if (m < R) update(L , R , v , rson);
        putup(rt);
    }
    int querySUM(int L,int R,int l,int r,int rt) {  //求区间L~R的和
        if (L <= l && r <= R) {
            return SUM[rt];
        }
        putdown(rt , r - l + 1);
        int m = (l + r) >> 1;
        int ret = 0;
        if (L <= m) ret += querySUM(L , R , lson);
        if (m < R) ret += querySUM(L , R , rson);
        return ret;
    }
    int queryMAX(int L,int R,int l,int r,int rt) {  //求区间L~R的最大值
        if (L <= l && r <= R) {
            return MAX[rt];
        }
        putdown(rt , r - l + 1);
        int m = (l + r) >> 1;
        int ret = -INF;
        if (L <= m) ret =max(ret,queryMAX(L , R , lson)) ;
        if (m < R) ret =max(ret,queryMAX(L , R , rson)) ;
        return ret;
    }
    int queryMIN(int L,int R,int l,int r,int rt) {  //求区间L~R的最小值
        if (L <= l && r <= R) {
            return MIN[rt];
        }
        putdown(rt , r - l + 1);
        int m = (l + r) >> 1;
        int ret = INF;
        if (L <= m) ret = min(ret,queryMIN(L , R , lson));
        if (m < R) ret = min(ret,queryMIN(L , R , rson));
        return ret;
    }
    int main() {
        int n , m;
        int a , b , c;
        char str[5];
        scanf("%d%d",&n,&m);
        build(1 , n , 1);
        while (m--) {
            scanf("%s",str);
            if (str[0] == 'S') {
                scanf("%d%d",&a,&b);
                printf("%d
    ",querySUM(a , b , 1 , n , 1));
            } else if(str[0]=='C') {
                scanf("%d%d%d",&a,&b,&c);
                update(a , b , c , 1 , n , 1);
            } else if(str[0]=='A') {
                scanf("%d%d",&a,&b);
                printf("%d
    ",queryMAX(a , b , 1 , n , 1));
            } else if(str[0]=='I') {
                scanf("%d%d",&a,&b);
                printf("%d
    ",queryMIN(a , b , 1 , n , 1));
            }
        }
        return 0;
    }

    AC代码

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    
    #define lson l , m , rt << 1
    #define rson m + 1 , r , rt << 1 | 1
    const int maxn = 50000+10;
    const int INF=0x7fffffff;
    int MAX[maxn<<2];
    int MIN[maxn<<2];
    int SUM[maxn<<2];
    int str[maxn];
    
    void PushUP(int rt) {
        MAX[rt] = max(MAX[rt<<1] , MAX[rt<<1|1]);
        MIN[rt] = min(MIN[rt<<1] , MIN[rt<<1|1]);
        SUM[rt] = SUM[rt<<1] + SUM[rt<<1|1];
    }
    
    void build(int l,int r,int rt) {
        if (l == r) {
            MAX[rt] = MIN[rt] = SUM[rt] = str[l];
            return ;
        }
        int m = (l + r) >> 1;
        build(lson);
        build(rson);
        PushUP(rt);
    }
    
    void update(int p,int addv,int l,int r,int rt) {
        if (l == r) {
            SUM[rt] = SUM[rt] + addv;
            MIN[rt] = MIN[rt] + addv;
            MAX[rt] =MAX[rt]+addv;
            return ;
        }
        int m = (l + r) >> 1;
        if (p <= m) update(p , addv ,lson);
        else update(p , addv , rson);
        PushUP(rt);
    }
    
    int querySUM(int L,int R,int l,int r,int rt) {
        if (L <= l && r <= R) {
            return SUM[rt];
        }
        int m = (l + r) >> 1;
        int ret = 0;
        if (L <= m) ret += querySUM(L , R , lson);
        if (R > m)  ret += querySUM(L , R , rson);
        return ret;
    }
    
    int main(){
        int n, m, score;
        char ch[10];
        int a, b;
        int T;
        scanf("%d",&T);
        for(int kase = 1; kase <= T; kase++)
        {
            printf("Case %d:
    ", kase);
            scanf("%d",&n);
            for(int i = 1; i <= n; i++){
                scanf("%d", &str[i]);
            }
            build(1, n, 1);
            for(;;)
            {
                scanf("%s", ch);
                if( ch[0] == 'E' )  break;
                scanf("%d%d",&a, &b);
                if( ch[0] == 'Q' )
                    printf("%d
    ",querySUM(a, b , 1 , n , 1));
                else if( ch[0] == 'A' )
                    update(a , b , 1 , n , 1);
                else if( ch[0] == 'S' )
                    update(a , -b , 1 , n , 1);
            }
        }
        return 0;
    }
    
  • 相关阅读:
    字节对齐方法
    以太网帧、IP报文格式
    单光纤udp通信
    错误笔记(1)——关于克隆虚拟机引发的后续问题
    linux 查看目录名称的方法
    rpm方式安装MySQL-5.6
    克隆虚拟机后修改MAC地址
    安卓反编译一些记录
    mysql日志
    Linux文件监控工具——inotify-tools
  • 原文地址:https://www.cnblogs.com/JinxiSui/p/9740525.html
Copyright © 2011-2022 走看看