Fill-Rect Query
Problem Statement
有一个 H × W H \times W H×W 的网格。初始时,每个格子中都写有字母 A。从顶部数第 i i i 行、从左数第 j j j 列的格子记为 ( i , j ) (i,j) (i,j)。
我们将按顺序执行 Q Q Q 次操作。
在第 i i i 次操作中,将以左上角 ( 1 , 1 ) (1,1) (1,1)、右下角 ( R i , C i ) (R_i,C_i) (Ri,Ci) 为对角线的矩形内的所有格子,覆盖为大写英文字母 X i X_i Xi。
请输出所有操作执行完毕后的网格。
Constraints
- 1 ≤ H , W 1 \le H,W 1≤H,W
- H × W ≤ 10 6 H \times W \le 10 ^ 6 H×W≤106
- 1 ≤ Q ≤ 2 × 10 5 1 \le Q \le 2 \times 10^5 1≤Q≤2×105
- 1 ≤ R i ≤ H 1 \le R_i \le H 1≤Ri≤H
- 1 ≤ C i ≤ W 1 \le C_i \le W 1≤Ci≤W
- X i X_i Xi 为大写英文字母。
- 所有输入数字均为整数。
Input
输入从标准输入中给出,格式如下:
H H H W W W Q Q Q
R 1 R_1 R1 C 1 C_1 C1 X 1 X_1 X1
R 2 R_2 R2 C 2 C_2 C2 X 2 X_2 X2
⋮ \vdots ⋮
R Q R_Q RQ C Q C_Q CQ X Q X_Q XQ
Output
输出 H H H 行。第 i i i 行应包括一个长度为 W W W 的字符串,其中第 j j j 个字符表示写在 ( i , j ) (i,j) (i,j) 上的字母。
Solution
由于 H × W ≤ 10 6 H \times W \le 10^6 H×W≤106,可以知道 min ( H , W ) ≤ 10 3 \min(H,W) \le 10^3 min(H,W)≤103。又行与列没有本质差别,不妨令 H ≤ 10 3 H \le 10^3 H≤103。
将每次操作 ( R i , C i , X i ) (R_i,C_i,X_i) (Ri,Ci,Xi) 转化为第 1 1 1 到 R i R_i Ri 行上的操作 ( C i , X i ) (C_i,X_i) (Ci,Xi),即在格子 1 1 1 到 C i C_i Ci 写上 X i X_i Xi。对于任意 i > j i>j i>j 满足 C i ≥ C j C_i \ge C_j Ci≥Cj,第 j j j 次操作对于满足 r ≤ R i r \le R_i r≤Ri 且 r ≤ R j r \le R_j r≤Rj 的第 r r r 行是无效的。所以用 H H H 个二元组栈存储每行的有效操作,加入操作时,将栈顶 C j ≥ C i C_j \ge C_i Cj≥Ci 的元素弹出,在将 ( C i , X i ) (C_i,X_i) (Ci,Xi) 入栈。最后将所有元素出栈,并依次记录到答案中。
对于每个操作,最多会在每行中出入栈一次,最后记录答案最多会写到 H × W H \times W H×W 个格子,所以总时间复杂度约为 O ( Q min ( H , W ) ) O(Q \min(H,W)) O(Qmin(H,W)),最大为 2 × 10 8 2 \times 10^8 2×108,在 AtCoder 上, 2 2 2 秒完全能跑完。
Code
cpp
#include<bits/stdc++.h>
#define int long long
using namespace std;
int h,w,q;
bool flag;
stack<pair<int,int> > qs[1005];
int ans[1000005];
int f(int x,int y){
return (x-1)*w+y-1;
}
void print(int x,int y){
cout<<char(ans[f(x,y)]+'A');
}
signed main(){
flag=0;
cin>>h>>w>>q;
if(h>w){
swap(h,w);
flag=1;
}
for(int i=1;i<=q;i++){
int r,c,x;
char ch;
cin>>r>>c>>ch;
x=ch-'A';
if(flag) swap(r,c);
for(int j=1;j<=r;j++){
while(!qs[j].empty()){
if(qs[j].top().first>c) break;
qs[j].pop();
}
qs[j].push({c,x});
}
}
for(int i=1;i<=h;i++){
int now=1;
while(!qs[i].empty()){
while(now<=qs[i].top().first){
ans[f(i,now)]=qs[i].top().second;
now++;
}
qs[i].pop();
}
}
if(flag){
for(int i=1;i<=w;i++){
for(int j=1;j<=h;j++){
print(j,i);
}
cout<<"\n";
}
}else{
for(int i=1;i<=h;i++){
for(int j=1;j<=w;j++){
print(i,j);
}
cout<<"\n";
}
}
return 0;
}