Codeforces Round #576 (Div. 2)
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 (1≤n≤2⋅10^5) — the numer of citizens.
The next line contains n integers a1, a2, ..., an (0≤ai≤10^9) — the initial balances of citizens.
The next line contains a single integer q (1≤q≤2⋅10^5) — 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 (1≤p≤n, 0≤x≤10^9), or 2 x (0≤x≤10^9). In the first case we have a receipt that the balance of the p-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
题意:题目意思就是给你n个数,m次操作,有两种不同的操作,
操作一就是单点修改,把指定位置的数改成所给的数。
操作二就是给你一个数,对于所有n个数,如果小于所给数就变成这个数。
最后要求输出操作后的整个数组。
思路:常规写法,可以用线段树维护一个最大值解决,单点修改+区间修改。
另外有一个神仙写法就是先把所有操作存起来,在从后往前预处理扫一遍操作,
我们可以根据操作2的查询计算最大值x,并记住每个公民的最后一个类型1的查询,
最后输出答案。
线段树写法:
1 #include<iostream>
2 #include<cstdio>
3 #include<cmath>
4 #include<cstring>
5 #include<algorithm>
6 #include<map>
7 #include<set>
8 #include<vector>
9 #include<queue>
10 #include<list>
11 #include<stack>
12 #include<unordered_map>
13 using namespace std;
14 #define ll long long
15 const int mod=1e9+7;
16 const int inf=1e9+100;
17
18 const int maxn=1e6+10;
19
20 typedef struct tree
21 {
22 int left;
23 int right;
24 int maxx;
25 int lan_mark;
26 } St;
27
28 St tree[maxn<<2];
29
30 int n,m;
31
32 inline void up(int k)
33 {
34 tree[k].maxx=max(tree[k<<1].maxx,tree[k<<1|1].maxx);
35 }
36
37 inline void build_tree(int k,int left,int right)
38 {
39 tree[k].left=left;
40 tree[k].right=right;
41 tree[k].lan_mark=0;
42 if(left==right)
43 {
44 scanf("%d",&tree[k].maxx);
45
46 return;
47 }
48
49 int mid=(left+right)>>1;
50
51 build_tree(k*2,left,mid);
52 build_tree(k<<1|1,mid+1,right);
53
54 up(k);
55 }
56
57 inline void down(int k)
58 {
59 int now=tree[k].lan_mark;
60
61 tree[k<<1].maxx=max(tree[k<<1].maxx,now);
62 tree[k<<1|1].maxx=max(tree[k<<1|1].maxx,now);
63
64 tree[k<<1].lan_mark=max(tree[k<<1].lan_mark,now);
65 tree[k<<1|1].lan_mark=max(tree[k<<1|1].lan_mark,now);
66
67 tree[k].lan_mark=0;
68 }
69
70 inline void update1(int k,int left,int right,int x)
71 {
72 if(tree[k].left>=left&&tree[k].right<=right)
73 {
74 tree[k].maxx=x;
75 return ;
76 }
77
78 if(tree[k].lan_mark)
79 down(k);
80
81 int mid=(tree[k].left+tree[k].right)>>1;
82
83 if(mid>=left)
84 update1(k<<1,left,right,x);
85
86 if(mid<right)
87 update1(k<<1|1,left,right,x);
88
89 up(k);
90 }
91
92 inline void update2(int k,int x)
93 {
94 tree[k].maxx=max(tree[k].maxx,x);
95 tree[k].lan_mark=max(tree[k].lan_mark,x);
96 return ;
97 }
98
99 inline int query(int k,int left,int right)
100 {
101 if(tree[k].left==left&&tree[k].right==right)
102 {
103 return tree[k].maxx;
104 }
105
106 int mid=(tree[k].left+tree[k].right)>>1;
107
108 if(tree[k].lan_mark)
109 down(k);
110
111 if(mid>=left)
112 return query(k<<1,left,right);
113
114 if(mid<right)
115 return query(k<<1|1,left,right);
116
117 }
118
119 int main()
120 {
121 // ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
122
123 scanf("%d",&n);
124
125 build_tree(1,1,n);
126
127 scanf("%d",&m);
128 int op;
129 int place,x;
130 for(int i=0;i<m;i++)
131 {
132 scanf("%d",&op);
133
134 if(op==1)
135 {
136 scanf("%d%d",&place,&x);
137
138 update1(1,place,place,x);
139 }
140 else if(op==2)
141 {
142 scanf("%d",&x);
143
144 update2(1,x);
145 }
146 }
147
148 for(int i=1;i<=n;i++)
149 {
150 printf("%d",query(1,i,i));
151
152 if(i==n)
153 printf("
");
154 else
155 printf(" ");
156 }
157
158 return 0;
159 }
神仙写法:
1 #include<iostream>
2 #include<cstdio>
3 #include<cmath>
4 #include<cstring>
5 #include<algorithm>
6 #include<map>
7 #include<set>
8 #include<vector>
9 #include<queue>
10 #include<list>
11 #include<stack>
12 #include<unordered_map>
13 using namespace std;
14 #define ll long long
15 const int mod=1e9+7;
16 const int inf=1e9+100;
17
18 const int maxn=2e5+10;
19
20 pair<int,int> v[maxn];
21
22 int quary[maxn];
23
24 int pre[maxn];
25
26 int main()
27 {
28 ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
29
30 int n,m,op;
31 int place,x;
32 while(cin>>n)
33 {
34 for(int i=0;i<n;i++)
35 {
36 cin>>v[i].first;
37 v[i].second=0;
38 }
39
40 cin>>m;
41 for(int i=0;i<m;i++)
42 {
43 cin>>op;
44
45 if(op==1)
46 {
47 cin>>place>>x;
48
49 v[place-1].first=x;
50 v[place-1].second=i;
51
52 quary[i]=-inf;
53
54 }
55 else if(op==2)
56 {
57 cin>>x;
58
59 quary[i]=x;
60
61 }
62 }
63 int maxx=-inf;
64
65 for(int i=m-1;i>=0;i--)
66 {
67 maxx=max(maxx,quary[i]);
68
69 pre[i]=maxx;
70 }
71
72 for(int i=0;i<n;i++)
73 {
74 cout<<max(v[i].first,pre[v[i].second]);
75 if(i==n-1)
76 cout<<endl;
77 else
78 cout<<" ";
79 }
80
81 }
82
83 return 0;
84 }