AtCoder Beginner Contest 464 E-Fill-Rect Query 题解
当时写的时候犯了糖......
错误解法
我第一眼看这题的时候想到了线段树
我们可以写一个哈希函数将一个二维数组映射为一维
将每一次修改分段处理(类似于树链剖分)
输出时单点查询即可
这样修改的复杂度最大为 \(O(hlog(hw))\)
查询总复杂度为 \(O(hwlog(hw))\)
按理说没有任何问题
but它T掉了
估计是有特殊构造(比如 \(h=10^6,w=1\))
错误code
#include<bits/stdc++.h>
using namespace std;
#define lid (id<<1)
#define rid (id<<1|1)
const int NUM=1e6+10;
struct tree{
int l,r;
int col='A';
int lazy='A';
}T[NUM<<2];
void pushdown(int id){
if(T[id].lazy!='A'){
int lz=T[id].lazy;
T[id].lazy='A';
T[lid].col=lz;
T[rid].col=lz;
T[lid].lazy=lz;
T[rid].lazy=lz;
}
}
void build(int id,int l,int r){
T[id].l=l,T[id].r=r;
if(l==r){
T[id].col='A';
return;
}
int mid=(l+r)>>1;
build(lid,l,mid);
build(rid,mid+1,r);
}
void update(int id,int l,int r,int val){
if(l<=T[id].l&&T[id].r<=r){
T[id].lazy=val;
T[id].col=val;
return;
}
pushdown(id);
int mid=(T[id].l+T[id].r)>>1;
if(l<=mid) update(lid,l,r,val);
if(r>mid) update(rid,l,r,val);
}
char query(int id,int pos){
if(T[id].l==T[id].r){
return T[id].col;
}
pushdown(id);
int mid=(T[id].l+T[id].r)>>1;
if(pos<=mid) return query(lid,pos);
if(pos>mid) return query(rid,pos);
}
int h,w,q;
int mp1(int i,int j){
return (i-1)*w+j;
}
void update1(int H,int W,int X){
for(int i=1;i<=H;++i) update(1,mp1(i,1),mp1(i,W),X);
}
signed main(){
ios::sync_with_stdio(0);
cin.tie(0),cout.tie(0);
cin>>h>>w>>q;
build(1,mp1(1,1),mp1(h,w)+10);
for(int i=1,R,C;i<=q;++i){
char X;
cin>>R>>C>>X;
update1(R,C,X);
}
for(int i=1;i<=h;++i){
for(int j=1;j<=w;++j){
cout<<query(1,mp1(i,j));
}cout<<'\n';
}
return 0;
}
正确解法
其实这非常简单
设 \(G\) 就是这个 \(H \times W\) 的矩阵,且初始值为一
对于每一次修改,将 \(G_{R_i,C_i}\) 修改为 \(i\),并记录每一个 \(X_i\)
记第 \(i\) 行,第 \(j\) 列的答案为 \(ans_{i,j}\)
然后就会发现 \(ans_{i,j}=\max_{i\le x\le H,j\le y\le W}{G_{x,y}}\)
说白了就是后缀最大值
我们倒着跑一遍 \(ans_{i,j}=\max{\{G_{i,j},ns_{i+1,j},ans_{i,j+1},ans_{i+1,j+1}\}}\)
然后对于每一个 \(ans_{i,j},\forall i \in [1,H],\forall j \in [1,W]\) 输出对应的 \(X\) 即可
AC code
#include<bits/stdc++.h>
using namespace std;
const int NUM=1e6+10;
int h,w,q;
char X[NUM]={'A'};
int mymax(int a,int b,int c,int d){
return max(max(a,b),max(c,d));
}
signed main(){
ios::sync_with_stdio(0);
cin.tie(0),cout.tie(0);
cin>>h>>w>>q;
vector<vector<int> > mp(h+2,vector<int>(w+2,0));
for(int i=1,R,C;i<=q;++i){
cin>>R>>C>>X[i];
mp[R][C]=i;
}
for(int i=h;i>=1;--i){
for(int j=w;j>=1;--j){
mp[i][j]=mymax(mp[i][j],mp[i+1][j],mp[i][j+1],mp[i+1][j+1]);
}
}
for(int i=1;i<=h;++i){
for(int j=1;j<=w;++j){
cout<<X[mp[i][j]];
}cout<<'\n';
}
return 0;
}
解释一下
vector<vector<int> > mp(h+2,vector<int>(w+2,0));
这是指建立一个长为 \(h+2\),宽为 \(w+2\),初始值为 \(0\),的二维数组
为神魔是 \(+2\)?
因为 vector 下标从零开始,且求 \(max\) 时需要访问到 \(mp_{h+1,w+1}\)
吐槽一句,为什么atcoder官解使用PYPY写的。

浙公网安备 33010602011771号