Description
There is a country with n citizens. The i-th of them initially has ai money. The government strictly controls the wealth of its citizens. Whenever a citizen makes a purchase or earns some money, they must send a receipt to the social services mentioning the amount of money they currently have.
Sometimes the government makes payouts to the poor: all citizens who have strictly less money than x are paid accordingly so that after the payout they have exactly x money. In this case the citizens don't send a receipt.
You know the initial wealth of every citizen and the log of all events: receipts and payouts. Restore the amount of money each citizen has after all events.
Input
The first line contains a single integer n — the numer of citizens.
The next line contains n integers — the initial balances of citizens.
The next line contains a single integer q — the number of events.
Each of the next q lines contains a single event. The events are given in chronological order.
Each event is described as either 1 p x , or 2 x . In the first case we have a receipt that the balance of the pp -th person becomes equal to x . In the second case we have a payoff with parameter x.
Output
Print n integers — the balances of all citizens after all events.
Examples
input
4
1 2 3 4
3
2 3
1 2 2
2 1
output
3 2 3 4
input
5
3 50 2 1 10
3
1 2 0
2 8
1 3 20
output
8 8 20 8 10
Note
In the first example the balances change as follows: 1 2 3 4 →→ 3 3 3 4 →→ 3 2 3 4 →→ 3 2 3 4
In the second example the balances change as follows: 3 50 2 1 10 →→ 3 0 2 1 10 →→ 8 8 8 8 10 →→ 8 8 20 8 10
题目大意:
有一串数据,对这串数据可进行以下两种操作:
1、更改任意位置的数据;
2、给定一个数据,将序列中所有小于这个数的数据都改为这个数。
要求给出q次操作后的序列。
分析:
由于线段树支持单点修改和区间更新,这题可用线段树解决。
每个区间维护该区间的最小值,延迟标记 tag 记录待更改的区间最小值(即操作2中给定的值)。若子区间的最小值大于 tag ,则不需下推(该区间不需更新),否则下推更新。
操作1则是正常的线段树单点修改。
最后查询每个叶子节点的值就是答案。这里必须依次查询,保证每个延迟标记都被下推到叶子节点。
具体解释见代码。
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <string>
#include <vector>
#include <set>
#include <cstdio>
#include <map>
#include <iomanip>
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define ll long long
#define INF 0x3f3f3f3f
using namespace std;
ll a[200005];
struct segtree{
int l,r;
ll minn;
int tag;//延迟标记
};
segtree t[200005*4];
void pushup(int p){//上推,维护区间最小值
int lson=p*2,rson=p*2+1;
t[p].minn=min(t[lson].minn,t[rson].minn);
}
void pushdown(int p){//将父节点的状态向下传递(延迟标记的传递)
if(t[p].tag!=-1){//说明父节点的状态已被改变
int lson=p*2,rson=p*2+1;
//子节点的tag小于父节点或者子节点未被更新,需要下推,另外下推后要用子节点的tag更新子节点区间的最小值
if(t[lson].tag<t[p].tag||t[lson].tag==-1) t[lson].tag=t[p].tag;
if(t[lson].minn<t[lson].tag) t[lson].minn=t[lson].tag;
if(t[rson].tag<t[p].tag||t[rson].tag==-1) t[rson].tag=t[p].tag;
if(t[rson].minn<t[rson].tag) t[rson].minn=t[rson].tag;
t[p].tag=-1;//父节点传递完成后标志复原
}
}
void build(int p,int l,int r){//建树
int mid=(l+r)/2;
t[p].l=l;
t[p].r=r;
t[p].tag=-1;
if(l==r){
t[p].minn=a[l];
return;
}
build(p*2,l,mid);
build(2*p+1,mid+1,r);
pushup(p);
}
//查询叶子节点的值
ll query(int index,int p){
if(t[p].l==t[p].r){
return t[p].minn;
}
pushdown(p);//首先将本节点的状态传递下去,便于接下来的递归查询
int lson=p*2;
int rson=p*2+1;
int mid=(t[p].l+t[p].r)/2;
if(index<=mid) return query(index,lson);
else return query(index,rson);
}
//单点修改
void change(int p,int index,ll num){
if(t[p].l==t[p].r){
t[p].minn=num;
t[p].tag=-1;
return;
}
int mid=(t[p].l+t[p].r)/2;
pushdown(p);//修改前要先下推
if(index<=mid){
change(p*2,index,num);
}
else{
change(p*2+1,index,num);
}
pushup(p);//修改完成后要上推
}
//区间更新
void update(int p,int L,int R,ll x){
int lson=p*2,rson=p*2+1;
if(L<=t[p].l&&R>=t[p].r){//区间被完全覆盖
if(t[p].minn<x){
t[p].tag=x;//这里区间的tag被更新为要求的值
t[p].minn=x;
}
return;//由于此处直接返回,所以需要延迟标记,此处未更新该节点的子树
}
pushdown(p);//进入子节点前先传递延迟标记,便于接下来的递归更新
int mid=(t[p].l+t[p].r)/2;
if(L<=mid){
update(lson,L,R,x);
}
if(R>mid){
update(rson,L,R,x);
}
pushup(p);//子节点更新返回后要更新父节点
}
int main(){
int n,q;
scanf("%d",&n);
rep(i,1,n){
scanf("%I64d",&a[i]);
}
build(1,1,n);
scanf("%d",&q);
rep(i,1,q){
int com;
scanf("%d",&com);
if(com==1){
int p;
ll x;
scanf("%d%I64d",&p,&x);
change(1,p,x);
}
else{
ll x;
scanf("%I64d",&x);
update(1,1,n,x);
}
}
rep(i,1,n){
printf("%I64d%c",query(i,1),(i==n?'\n':' '));
}
return 0;
}