题目描述
给定一个长度为 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-1n−1。
接下来 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 - 1i−1的元素的值。
输入输出样例
说明
- 子任务#1(8分):满足 1 leq n leq 10 000, 1 leq k leq 5 0001≤n≤10000,1≤k≤5000;
- 子任务#2(24分):满足 1 leq n leq 100 000, 1 leq k leq 500 0001≤n≤100000,1≤k≤500000,全部增加操作均在全部移除操作之前;
- 子任务#3(29分):满足 1 leq n leq 100 000, 1 leq k leq 500 0001≤n≤100000,1≤k≤500000;
- 子任务#4(39分):满足 1 leq n leq 2 000 000, 1 leq k leq 500 0001≤n≤2000000,1≤k≤500000。
所有操作的高度 hh满足 0 leq h leq 100 0000≤h≤100000。
题解
- 就是对区间取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 }