• HDU_1698 Just a Hook(线段树+lazy标记)


    题目请点我
    题解:
    接触到的第一到区间更新,须要用到lazy标记。典型的区间着色问题。
    lazy标记详情请參考博客:http://ju.outofmemory.cn/entry/99351
    简单讲就是被lazy标记的非叶子节点所包括的全部叶子节点具有同样的性质。当更新或查询到该区间时,不再向下递归。仅对当前节点的lazy标记进行改动。

    update :
    假设当前区间刚好全然在目的区间内:看当前节点是否被标记。若未被标记。或者被标记了可是与要更新类型同样,不再向下更新。仅标记当前节点。若当前节点已经被标记且与要更新类型不同,运行pushdown操作。标记下移,递归进行更新。


    query:
    假设当前节点区间在目的区间内(事实上一定在。由于题目要求1~N总的价值),若节点被标记,返回segTree[i]*(r+1-l);若当前节点未被标记或者区间不能全然覆盖,递归求解。

    代码实现:

    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #define MAX 100010
    #define LCHILD(x) x<<1
    #define RCHILD(x) x<<1|1
    #define MID(x,y) (x+y)>>1
    
    using namespace std;
    
    int T;
    int res;
    int N,Q;
    int segTree[MAX<<2|1];
    void pushdown(int root);
    void build(int root,int l,int r);
    int query(int a,int b,int l,int r,int root);
    void update(int a,int b,int l,int r,int root,int type);
    int main()
    {
        scanf("%d",&T);
        for( int t = 1; t <= T; t++ ){
            scanf("%d",&N);
            scanf("%d",&Q);
            build(1,1,N);
            while( Q-- ){
                int a,b,c;
                scanf("%d%d%d",&a,&b,&c);
                update(a,b,1,N,1,c);
            }
            int res = query(1,N,1,N,1);
            printf("Case %d: The total value of the hook is %d.
    ",t,res);
        }
        return 0;
    }
    
    void build(int root,int l,int r){
        if( l == r ){
            segTree[root] = 1;
            return ;
        }
        int mid = MID(l,r);
        build(LCHILD(root),l,mid);
        build(RCHILD(root),mid+1,r);
        //非叶子节点初始为0。表示不标记
        segTree[root] = 0;
    }
    
    void update(int a,int b,int l,int r,int root,int type){
        //不在当前区间
        if( l > b || r < a ){
            return ;
        }
        //更新区间全然在当前区间内或者type同样
        if( (l >= a && r <= b) || segTree[root] == type ){
            segTree[root] = type;
            return ;
        }
        //当前节点被标记可是type不同
        if( segTree[root] != 0 ){
            pushdown(root);
        }
        int mid = MID(l,r);
        update(a,b,l,mid,LCHILD(root),type);
        update(a,b,mid+1,r,RCHILD(root),type);
        return ;
    }
    
    int query(int a,int b,int l,int r,int root){
        //不在当前区间
        if( l > b || r < a ){
            return 0;
        }
        int mid = MID(l,r);
        if( l >= a && r <= b ){
            if( segTree[root] != 0 ){
                //闭区间[l,r]
                return segTree[root]*(r+1-l);
            }
            else{
                return query(a,b,l,mid,LCHILD(root))+query(a,b,mid+1,r,RCHILD(root));
            }
        }
        else{
            return query(a,b,l,mid,LCHILD(root))+query(a,b,mid+1,r,RCHILD(root));
        }
    }
    
    void pushdown(int root){
        segTree[LCHILD(root)] = segTree[root];
        segTree[RCHILD(root)] = segTree[root];
        segTree[root] = 0;
        return ;
    }
    
  • 相关阅读:
    DB-MySQL:MySQL 正则表达式
    DB-MySQL:MySQL 事务
    DB-MySQL:MySQL 索引
    DB-MySQL:MySQL 临时表
    DB-MySQL:MySQL 复制表
    DB-MySQL:MySQL 序列使用
    DB-MySQL:MySQL 处理重复数据
    DB-MySql:MySQL 及 SQL 注入
    mysql
    PHP+jQuery 注册模块的改进之一:验证码存入SESSION
  • 原文地址:https://www.cnblogs.com/zsychanpin/p/7281902.html
Copyright © 2020-2023  润新知