题解:CF1989F Simultaneous Coloring
CF1989F Simultaneous Coloring 题解
前言
2024/7/6 update:修改了时间复杂度。
题意
给定一个
分析
很像一年前的某音的小游戏。
首先考虑平方代价这个东西,显然每次操作选择的数量越少越好,所以我们考虑如何选择。
再考虑,某个格子的颜色是由该格子最后一次染色来决定的,假如第
这样就可以构造出一张有向图。假设图为 DAG,那么直接拓扑排序就可以构造出一组解,显然此时答案为
但是此时时间复杂度为
容易想到用并查集来维护 SCC 的合并,所以我们需要用到一种算法来判断每一条边会合并哪些 SCC。
可以考虑把加边通过每个要求的先后时间来整体二分。
我们对于一个当前区间
如果当前区间
否则如果
整体二分复杂度
代码
const int N=4e5+2;
int n,m,q,ans;
struct Graph{
int u,v,tim;
};
vector<int>E[N];
struct edge{
int nxt,v;
}ed[N];
int en,first[N];
void add(int u,int v){
ed[++en]={first[u],v};
first[u]=en;
}
int dfn[N],low[N],cnt;
int num,id[N];
bool vis[N],flg[N];
stack<int>st;
void dfs(int u){
dfn[u]=low[u]=++cnt;
st.push(u);vis[u]=1;
for(int i=first[u];i;i=ed[i].nxt)
if(!dfn[ed[i].v])dfs(ed[i].v),low[u]=min(low[u],low[ed[i].v]);
else if(vis[ed[i].v])low[u]=min(low[u],low[ed[i].v]);
if(dfn[u]==low[u]){
num++;int x;
do{
x=st.top();st.pop();
id[x]=num,vis[x]=0;
}while(x!=u);
}
return;
}
void solve(int l,int r,vector<Graph>G){
int mid=(l+r)>>1;
en=cnt=num=0;
for(Graph i:G)
first[i.u]=first[i.v]=
dfn[i.u]=dfn[i.v]=0,
vis[i.u]=vis[i.v]=0;
for(Graph i:G)
if(i.tim<=mid)add(i.u,i.v);
for(Graph i:G){
if(!dfn[i.u])dfs(i.u);
if(!dfn[i.v])dfs(i.v);
}
if(l==r){
for(Graph i:G)if(id[i.u]==id[i.v])E[mid].push_back(i.tim);
return;
}
vector<Graph>Gl,Gr;
for(Graph i:G){
if(id[i.u]==id[i.v]){
if(i.tim<=mid)Gl.push_back(i);
}
else Gr.push_back({id[i.u],id[i.v],i.tim});
}
solve(l,mid,Gl);solve(mid+1,r,Gr);
}
int fa[N],siz[N];
inline int find(int v){return fa[v]==v?v:fa[v]=find(fa[v]);}
inline int pf(const int x){return x==1?0:x*x;}
void merge(int x,int y){
x=find(x);y=find(y);
if(x!=y){
ans-=pf(siz[x]),ans-=pf(siz[y]);
if(siz[x]<siz[y])swap(x,y);
fa[y]=x,siz[x]+=siz[y];
ans+=pf(siz[x]);
}
}
signed main(){
n=read();m=read();q=read();
vector<Graph>G;
for(int i=1;i<=q;i++){
int x=read(),y=read()+n;
if(getchar()=='R')G.push_back({y,x,i});
else G.push_back({x,y,i});
}
solve(1,q,G);
for(int i=1;i<=n+m;i++)fa[i]=i,siz[i]=1;
for(int i=1;i<=q;i++){
for(int j:E[i])
merge(G[j-1].u,G[j-1].v);
printf("%lld\n",ans);
}
return 0;
}