D. Welfare State(线段树)

Problem - D - Codeforces

D. Welfare State(线段树)_第1张图片

有一个国家有n个公民。其中第i个公民最初拥有ai钱。政府严格控制其公民的财富。每当一个公民购买东西或赚到一些钱,他们必须向社会服务部门寄送一张收据,提到他们目前拥有的钱的数量。

有时,政府会对穷人进行赔付:所有钱数严格少于x的公民都会得到相应的赔付,这样在赔付后他们正好有x的钱。在这种情况下,公民们不会发送收据。

你知道每个公民的初始财富和所有事件的记录:收据和赔款。恢复每个公民在所有事件后拥有的钱数。

输入
第一行包含一个整数n(1≤n≤2⋅105)--公民的数量。

下一行包含n个整数a1, a2, ..., an (0≤ai≤109) - 公民的初始余额。

下一行包含一个整数q(1≤q≤2⋅105)--事件的数量。

接下来的q行中的每一行都包含一个单一的事件。事件是按时间顺序给出的。

每个事件被描述为1 p x (1≤p≤n, 0≤x≤109),或2 x (0≤x≤109)。在第一种情况下,我们有一张收据,即第p个人的余额变得等于x。在第二种情况下,我们有一个参数为x的报酬。

输出
打印n个整数 - 所有事件后所有公民的余额。

例子
输入 复制

4
1 2 3 4
3
2 3
1 2 2
2 1
1
2
3
4
5
6
输出 复制

3 2 3 4 
1
输入 复制

5
3 50 2 1 10
3
1 2 0
2 8
1 3 20
1
2
3
4
5
6
输出 复制

8 8 20 8 10 
1
注意
在第一个例子中,余额变化如下: 1 2 3 4 → 3 3 3 4 → 3 2 3 4 → 3 2 3 4

在第二个例子中,余额的变化如下: 3 50 2 1 10 → 3 0 2 1 10 → 8 8 8 8 10 → 8 8 20 8 10
题解:

用最小值来记录答案,这样进行区间修改的时候,可以看到,当前数用不用修改

pushdown下放时,应该取与上一级的mi的max(修改最终答案,因为单点最小值就是我们维护的最终答案,这题与普通修改值的线段树不同的就是,他是利用mi记录的答案),和lazy的max(代表是否被更大的lazy取代)

#include 
#include 
#include 
#include
#include
#include
#include
#include
#include
using namespace std;
typedef long long ll;
#define int long long
typedef pair PII; 
const int N = 2e5 + 10;
struct node
{
	int lazy;
	int mi;
	int l,r;
}tre[N*4];
int v[N];
void pushup(int rt)
{
	tre[rt].mi = min(tre[rt*2].mi,tre[rt*2 + 1].mi);
}
void build(int rt,int l,int r)
{
	tre[rt].lazy = 0;
	tre[rt].l = l;
	tre[rt].r = r;
	if(l == r)
	{
		tre[rt].mi = v[l];
		return ;
	}
	int mid = (l + r)/2;
	build(rt*2,l,mid);
	build(rt*2 + 1,mid + 1,r);
	pushup(rt);
}
void pushdown(int rt)
{
	if(tre[rt].lazy)
	{
		tre[rt*2].mi = max(tre[rt].mi,tre[rt*2].mi);
		tre[rt*2].lazy = max(tre[rt].lazy,tre[rt*2].lazy);
		tre[rt*2+1].mi = max(tre[rt].mi,tre[rt*2+1].mi);
		tre[rt*2+1].lazy = max(tre[rt].lazy,tre[rt*2+1].lazy);
	}
	tre[rt].lazy = 0;
}
void updata1(int rt,int pos,int x)
{
	if(tre[rt].l == tre[rt].r)
	{
		tre[rt].mi = x;
		return ;
	}
	pushdown(rt);
	int mid = (tre[rt].l + tre[rt].r)/2;
	if(pos <= mid)
	{
		updata1(rt*2,pos,x);
	}
	else
	{
		updata1(rt*2 + 1,pos,x);
	}
	pushup(rt);
}
void updata2(int rt,int x)
{
	if(tre[rt].mi >= x)
	return ;
	else
	{
		tre[rt].lazy = tre[rt].mi = x;
	}
}
int ask(int rt,int pos)
{
	if(tre[rt].l == tre[rt].r)
	{
		return tre[rt].mi;
	}
	int mid = (tre[rt].l + tre[rt].r)/2;
	pushdown(rt);
	if(pos <= mid)
	{
		return ask(rt*2,pos);
	}
	else
	{
		return ask(rt*2 + 1,pos);
	}
	pushup(rt);
}
void solve()
{
	int n;
	cin >> n;
	for(int i = 1;i <= n;i++)
	{
		cin >> v[i];
	}
	build(1,1,n);
	int m;
	cin >> m;
	for(int i = 1;i <= m;i++)
	{
		int op;
		cin >> op;
		if(op == 1)
		{
			int pos,x;
			cin >> pos >> x;
			updata1(1,pos,x);
		}
		else
		{
			int x;
			cin >> x;
			updata2(1,x);
		}
	}
	for(int i = 1;i <= n;i++)
	cout <> t;
	while(t--)
	{
		solve(); 
	}
}

你可能感兴趣的:(算法)