• [线段树] Luogu P4560 砖墙


    题目描述

    给定一个长度为 nn且初始值全为 00的序列。你需要支持以下两种操作:

    • Add L, R, hL,R,h:将序列 [L, R][L,R]内所有值小于 hh的元素都赋为 hh,此时不改变高度大于 hh的元素值
    • Remove L, R, hL,R,h:将序列 [L, R][L,R]内所有值大于 hh的元素都赋为 hh,此时不改变高度小于 hh的元素值

    你需要输出进行 kk次上述操作之后的序列。

    输入输出格式

    输入格式:

    输入的第一行包含两个正整数 n, kn,k,分别表示序列中元素的个数以及操作数量,注意:序列下标编号为 00 ~ n-1n1。

    接下来 kk行每行包含 44个整数 t, L, R, ht,L,R,h,若 t = 1t=1则表明为 Add 操作,若 t = 2t=2则表明为 Remove 操作。 L, R, hL,R,h的含义见题目描述。

    输出格式:

    输出包含 nn行,每行包含 11个整数。第 ii行的整数表示 kk次操作之后序列中编号为 i - 1i1的元素的值。

    输入输出样例

    输入样例#1:
    10 3
    1 3 4 91220
    1 5 9 48623
    2 3 5 39412
    
    输出样例#1:
    0
    0
    0
    39412
    39412
    39412
    48623
    48623
    48623
    48623
    
    输入样例#2:
    10 6
    1 1 8 4
    2 4 9 1
    2 3 6 5
    1 0 5 3
    1 2 2 5
    2 6 7 0
    
    输出样例#2: 
    3
    4
    5
    4
    3
    3
    0
    0
    1
    0
    

    说明

    • 子任务#1(8分):满足 1 leq n leq 10 000, 1 leq k leq 5 0001n10000,1k5000;
    • 子任务#2(24分):满足 1 leq n leq 100 000, 1 leq k leq 500 0001n100000,1k500000,全部增加操作均在全部移除操作之前;
    • 子任务#3(29分):满足 1 leq n leq 100 000, 1 leq k leq 500 0001n100000,1k500000;
    • 子任务#4(39分):满足 1 leq n leq 2 000 000, 1 leq k leq 500 0001n2000000,1k500000。

    所有操作的高度 hh满足 0 leq h leq 100 0000h100000。

    题解

    • 就是对区间取min和取max,比较简单的一道线段树

    题解

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <iostream>
     4 #define N 2000010
     5 using namespace std;
     6 int n,m;
     7 struct Tree
     8 {
     9     int mx[N*4],mn[N*4];
    10     void Max(int x,int y) { mn[x]=max(mn[x],y),mx[x]=max(mx[x],y); }
    11     void Min(int x,int y) { mn[x]=min(mn[x],y),mx[x]=min(mx[x],y); } 
    12     void pushdown(int d) { Max(d*2,mx[d]),Max(d*2+1,mx[d]),Min(d*2,mn[d]),Min(d*2+1,mn[d]),mx[d]=0,mn[d]=0x7fffffff; }    
    13     void update(int d,int L,int R,int l,int r,int x,int y)
    14     {
    15         if (L<=l&&r<=R) { if (y==0) Max(d,x); else Min(d,x); return; }
    16         int mid=l+r>>1;
    17         pushdown(d);
    18         if (L<=mid) update(d*2,L,R,l,mid,x,y);
    19         if (R>mid) update(d*2+1,L,R,mid+1,r,x,y);
    20     } 
    21     void query(int d,int l,int r)
    22     {
    23         if (l==r) { printf("%d
    ",mx[d]); return; }
    24         int mid=l+r>>1;
    25         pushdown(d),query(d*2,l,mid),query(d*2+1,mid+1,r);
    26     }    
    27 }tree;
    28 int main()
    29 {
    30     scanf("%d%d",&n,&m);
    31     for (int i=1;i<=n*4;i++) tree.mn[i]=0x7fffffff;
    32     for (int i=1,op,l,r,h;i<=m;i++) scanf("%d%d%d%d",&op,&l,&r,&h),tree.update(1,l+1,r+1,1,n,h,op-1);
    33     tree.query(1,1,n);
    34 } 
  • 相关阅读:
    IBM Minus One(water)
    约瑟夫问题的循环链表实现
    双向链表(差不多)
    单向链表的建立,插入,删除(复习一下)
    找新朋友(欧拉函数)
    验证角谷猜想(hd1279)
    Wolf and Rabbit(gcd)
    Big Number(大数)
    字串数(高精度组合数)
    寻找素数对(hd1262)
  • 原文地址:https://www.cnblogs.com/Comfortable/p/11199199.html
Copyright © 2020-2023  润新知