My Blogs
[ARC179E] Rectangle Concatenation
唐完了。
稍微觀察一下發現矩形只有兩種形態。考慮暴力:從每個 \(i\) 開始向後掃,設 \(f_{j,0}\) 表示能否拼在左右,\(f_{j,1}\) 表示能否拼在上下。設 \(S_{l,r}\) 表示 \([l,r]\) 內矩形的面積和,沒想到用面積判就敗了:
\[\begin{aligned}
f_{j,0}=(f_{j-1,0}\wedge x_j=x_{j-1})\vee(f_{j-1,1}\wedge S(i,j-1)=y_{j-1}x_j)\\
f_{j,1}=(f_{j-1,1}\wedge y_j=y_{j-1})\vee(f_{j-1,0}\wedge S(i,j-1)=x_{j-1}y_j)\\
\end{aligned}
\]
考慮最佳化:把 \(j\) 從左向右掃,維護合法的 \(i\)。設 \(S_0\) 表示 \(f_{j,0}\) 合法的 \(i\) 集合,\(S_1\) 同理。發現 \(j+1\) 的時候,觀察式子左半部分,\(S_0,S_1\) 可能會做一個清空操作。
右半部分看成面積字首和相減,合法的 \(i\) 是唯一的。是一個單點加入,容易維護。還需要拿一個桶維護 \(|S_0\cup S_1|\)。時間複雜度 \(\mathcal O(n\log n)\) 或者 \(\mathcal O(n)\)。
int n,s[300010],vis[300010],f0[300010],f1[300010],ans,sum;
pii a[300010];
inline void add(int x){sum+=!vis[x]++;}
inline void del(int x){sum-=!--vis[x];}
map<int,int> hash;
inline void mian()
{
read(n),hash[0]=0;vi v0,v1;
for(int i=1;i<=n;++i)read(a[i].fi,a[i].se),s[i]=s[i-1]+a[i].fi*a[i].se,hash[s[i]]=i;
ans=1,add(1),add(1),v0.eb(1),v1.eb(1),f0[1]=f1[1]=1;
for(int i=2;i<=n;++i)
{
int va0=1;
if(hash.find(s[i-1]-a[i].se*a[i-1].fi)!=hash.end())va0=f0[hash[s[i-1]-a[i].se*a[i-1].fi]+1];
int va1=1;
if(hash.find(s[i-1]-a[i].fi*a[i-1].se)!=hash.end())va1=f1[hash[s[i-1]-a[i].fi*a[i-1].se]+1];
if(a[i].fi!=a[i-1].fi){for(auto p:v0)del(p),f0[p]=0;v0.clear();}
if(a[i].se!=a[i-1].se){for(auto p:v1)del(p),f1[p]=0;v1.clear();}
int S=s[i-1]-a[i].fi*a[i-1].se;
if(hash.find(S)!=hash.end()&&!f0[hash[S]+1]&&va1)
add(hash[S]+1),v0.eb(hash[S]+1),f0[hash[S]+1]=1;
S=s[i-1]-a[i].se*a[i-1].fi;
if(hash.find(S)!=hash.end()&&!f1[hash[S]+1]&&va0)
add(hash[S]+1),v1.eb(hash[S]+1),f1[hash[S]+1]=1;
if(!f0[i])add(i),v0.eb(i),f0[i]=1;
if(!f1[i])add(i),v1.eb(i),f1[i]=1;
ans+=sum;
}
write(ans);
}