n個の市民と国があります。それらのi番目のは最初のAIお金を持っています。政府は、厳密にその市民の富を制御します。市民が買い物をするか、いくつかのお金を稼いでいるときはいつでも、彼らは、彼らが現在持っているお金の量を言及する社会サービスへの領収書を送信する必要があります。
支払いの後、彼らは正確にXお金を持っているように、xがそれに応じて支払われるより厳密に少ないお金を持っているすべての市民:たまに政府が貧困層への支払いを行います。この場合、市民は領収書を送信しません。
領収書や支払い:あなたはすべての市民の最初の富とすべてのイベントのログを知っています。すべてのイベントの後、各市民が持っているお金の量を復元します。
入力
市民のNUMER - 最初の行は、単一の整数n(^ 51≤n≤2⋅10)を含有します。
市民の初期残高 - 次の行には、n個の整数のA1、A2、...、(0≤ai≤10^ 9)が含まれています。
イベントの数 - 次の行は、単一の整数q(^ 51≤q≤2⋅10)を含有します。
次のqラインの各々は、単一のイベントが含まれています。イベントは、年代順に記載されています。
各イベントは、1つのピクセル(1≤p≤n、^ 90≤x≤10)、または2×(^ 90≤x≤10)のいずれかとして記載されています。最初のケースでは、p番目の人のバランスがxに等しくなる領収書を持っています。後者の場合では、パラメータxとのペイオフを持っています。
出力
印刷n個の整数 - すべてのイベントの後にすべての市民の残高。
例
入力
4
1 2 3 4
3
2 3
1 2 2
2 1
出力
3 2 3 4
入力
5
3 50 2 1 10
3
1 2 0
2 8
1 3 20
出力
8 8 20 8 10
注意
次のように最初の例で残高は変更: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:次のように第2の例では残高は変更します
题意:题目意思就是给你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("\n");
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 }