B. Welfare State
题目链接
B. Welfare State
一个数组,两种操作,然后输出最终数组,两种操作是:
1 p x
: 表示将第 \(p\) 个数改为 \(x\);
2 x
: 表示将所有小于 \(x\) 的数改成 \(x\);
解题思路
思维
首先可以肯定的一点:后面的 \(2\) 操作可能会对前面的值产生影响,这种影响有后往前取最大值即可,而操作 \(1\) 与顺序有关,可以记录操作 \(1\) 最后一次的影响,如果后面有操作 \(2\),取两者影响的最大值即可,注意,如果某个位置的数没有经过单点修改的话则取操作 \(2\) 的最大值
- 时间复杂度:\(O(n)\)
线段树
关键在于操作 \(2\),即对于值域的修改,打懒标记,由于是全局性的修改,直接对根节点打上懒标记即可,另外注意线段树的写法
- 时间复杂度:\(O(qlogn)\)
代码
- 思维
// %%%Skyqwq
#include <bits/stdc++.h>
//#define int long long
#define help {cin.tie(NULL); cout.tie(NULL);}
#define pb push_back
#define fi first
#define se second
#define mkp make_pair
using namespace std;
typedef long long LL;
typedef pair<int, int> PII;
typedef pair<LL, LL> PLL;
template <typename T> bool chkMax(T &x, T y) { return (y > x) ? x = y, 1 : 0; }
template <typename T> bool chkMin(T &x, T y) { return (y < x) ? x = y, 1 : 0; }
template <typename T> void inline read(T &x) {
int f = 1; x = 0; char s = getchar();
while (s < '0' || s > '9') { if (s == '-') f = -1; s = getchar(); }
while (s <= '9' && s >= '0') x = x * 10 + (s ^ 48), s = getchar();
x *= f;
}
const int N=1e6+5;
int n,q,lst[N],a[N],b[N];
int main()
{
scanf("%d%d",&n,&q);
for(int i=1;i<=n;i++)scanf("%d",&a[i]);
for(int i=1;i<=q;i++)
{
int op,x,y;
scanf("%d",&op);
if(op==1)
{
scanf("%d%d",&x,&y);
a[x]=y;
lst[x]=i;
}
else
{
scanf("%d",&x);
b[i]=x;
}
}
for(int i=q-1;~i;i--)b[i]=max(b[i],b[i+1]);
for(int i=1;i<=n;i++)printf("%d ",max(a[i],b[lst[i]]));
return 0;
}
- 线段树
// %%%Skyqwq
#include <bits/stdc++.h>
//#define int long long
#define help {cin.tie(NULL); cout.tie(NULL);}
#define pb push_back
#define fi first
#define se second
#define mkp make_pair
using namespace std;
typedef long long LL;
typedef pair<int, int> PII;
typedef pair<LL, LL> PLL;
template <typename T> bool chkMax(T &x, T y) { return (y > x) ? x = y, 1 : 0; }
template <typename T> bool chkMin(T &x, T y) { return (y < x) ? x = y, 1 : 0; }
template <typename T> void inline read(T &x) {
int f = 1; x = 0; char s = getchar();
while (s < '0' || s > '9') { if (s == '-') f = -1; s = getchar(); }
while (s <= '9' && s >= '0') x = x * 10 + (s ^ 48), s = getchar();
x *= f;
}
const int N=1e6+5;
int n,q;
struct Tr
{
int l,r,val,lazy;
}tr[4*N];
void pushup(int p)
{
tr[p].val=max(tr[p<<1].val,tr[p<<1|1].val);
}
void pushdown(int p)
{
if(tr[p].lazy)
{
int &add=tr[p].lazy;
tr[p<<1].val=max(tr[p<<1].val,add);
tr[p<<1|1].val=max(tr[p<<1|1].val,add);
tr[p<<1].lazy=max(tr[p<<1].lazy,add);
tr[p<<1|1].lazy=max(tr[p<<1|1].lazy,add);
add=0;
}
}
void build(int p,int l,int r)
{
tr[p]={l,r,0,0};
if(l==r)
{
scanf("%d",&tr[p].val);
tr[p].lazy=tr[p].val;
return ;
}
int mid=l+r>>1;
build(p<<1,l,mid);
build(p<<1|1,mid+1,r);
pushup(p);
}
void change1(int p,int l,int r,int x,int y)
{
if(l==r)
{
tr[p].val=y;
return ;
}
pushdown(p);
int mid=l+r>>1;
if(x<=mid)change1(p<<1,l,mid,x,y);
else
change1(p<<1|1,mid+1,r,x,y);
pushup(p);
}
void change2(int p,int y)
{
tr[p].lazy=max(tr[p].lazy,y);
tr[p].val=max(tr[p].val,y);
}
int ask(int p,int l,int r,int x)
{
if(l==r)return tr[p].val;
pushdown(p);
int mid=l+r>>1;
if(x<=mid)return ask(p<<1,l,mid,x);
else
return ask(p<<1|1,mid+1,r,x);
pushup(p);
}
int main()
{
scanf("%d%d",&n,&q);
build(1,1,n);
while(q--)
{
int op,x,y;
scanf("%d",&op);
if(op==1)
{
scanf("%d%d",&x,&y);
change1(1,1,n,x,y);
}
else
{
scanf("%d",&y);
change2(1,y);
}
}
for(int i=1;i<=n;i++)printf("%d ",ask(1,1,n,i));
return 0;
}