题解:AT_abc464_e

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;
}