LGP10834 [COTS 2023] Zadatak 学习笔记
LGP10834 [COTS 2023] Zadatak 学习笔记
题意简述
有 \(n\) 个黑色的正方形,标号为 \(1\sim n\),第 \(i\) 个正方形边长为 \(a_i\)。保证所有 \(a_i\) 均为偶数。
接下来有 \(n-1\) 次操作:将 \(x_i\)、\(y_i\) 两个正方形对齐中心,合并为 \(n+i\) 号正方形。新正方形为原来两个正方形在颜色上的“异或和”(同色则白,异色则黑)。定义这次合并的代价为两个正方形与的面积(即两个正方形中都是黑色的面积)。
输出每次合并的代价。
\(n\le 10^5\),\(a_i\le 10^6\)。
做法解析
这道题具有很明显的指向性。题目的整个过程就完全是一个合并的过程,所以你显然要用某种合并算法来解决问题。由于线段树功能强大,这题有类似求和、求与、异或的这一些东西,看起来比较复杂,所以我们考虑线段树合并。
我们怎么维护一个方形的颜色和面积信息呢?首先正方形是上下左右都对称的,我们不妨维护其中一角,代价就是这一角乘四,也就是让我们处理操作中的 \(a_i\) 除以二。
这么做是因为我们维护正方形的方式使然。我们像洋葱一样维护正方形。不妨称呼第 \(i\) 圈为边长 \(i\) 的正方形减去边长 \(i-1\) 的正方形(无关颜色)的那部分。我们维护这些圈的黑白。初始相当于给每个 rt 的 \([1,a_i]\) 区间记为黑的。然后代价就是合并的时候直接算就行。
代码实现
显然,我们对于一个区间改我们不能总是递归到 cl==cr,而是仍然拆成 \(O(\log V)\) 个结点。这样才能保证我们的时空复杂度。
#include <bits/stdc++.h>
using namespace std;
using namespace obasic;
const int MaxN=1e5+5;
int N,A[MaxN],X,Y,V=5e5;
lolo calc(int l,int r){return 1ll*r*r-1ll*(l-1)*(l-1);}
int srt[MaxN<<1];
struct SegTrees{
lolo vol[MaxN*40],sum[MaxN*40];
int tag[MaxN*40],ls[MaxN*40],rs[MaxN*40],tot;
void pushup(int u){sum[u]=sum[ls[u]]+sum[rs[u]];}
void maketag(int u,int x){sum[u]=vol[u]-sum[u],tag[u]^=x;}
void pushdown(int u){if(tag[u])maketag(ls[u],tag[u]),maketag(rs[u],tag[u]),tag[u]=0;}
void modify(int &u,int cl,int cr,int dl,int dr,int x){
if(!u)u=++tot,vol[u]=calc(cl,cr);
if(dl<=cl&&cr<=dr){maketag(u,x);return;}
int cmid=(cl+cr)>>1;
if(!ls[u])ls[u]=++tot,vol[ls[u]]=calc(cl,cmid);
if(!rs[u])rs[u]=++tot,vol[rs[u]]=calc(cmid+1,cr);
pushdown(u);
if(dl<=cmid)modify(ls[u],cl,cmid,dl,dr,x);
if(dr>cmid)modify(rs[u],cmid+1,cr,dl,dr,x);
pushup(u);
}
pil merge(int u,int v,int cl,int cr){
if(!u||!v)return {u|v,0};
if(!sum[u])return {v,0};
if(!sum[v])return {u,0};
lolo tmp;
if(sum[u]==vol[u]){tmp=sum[v],maketag(v,1);return {v,tmp};}
if(sum[v]==vol[v]){tmp=sum[u],maketag(u,1);return {u,tmp};}
if(cl==cr){tmp=(sum[u]&&sum[v])*vol[u],sum[u]^=sum[v];return {u,tmp};}
int cmid=(cl+cr)>>1;lolo cres=0;pushdown(u),pushdown(v);
auto [cls,lres]=merge(ls[u],ls[v],cl,cmid);ls[u]=cls,cres+=lres;
auto [crs,rres]=merge(rs[u],rs[v],cmid+1,cr);rs[u]=crs,cres+=rres;
pushup(u);return {u,cres};
}
}SgS;
int main(){
readi(N);
for(int i=1;i<=N;i++)readi(A[i]),A[i]>>=1,SgS.modify(srt[i],1,V,1,A[i],1);
for(int i=1;i<N;i++){
readis(X,Y);
auto [crt,ans]=SgS.merge(srt[X],srt[Y],1,V);
srt[i+N]=crt;writil(ans<<2);
}
return 0;
}
浙公网安备 33010602011771号