【总结】ABC219题解报告

E - Moat

题意:求能包含所有村庄的形状为 多边形 的栅栏数量。

思路一 . 直接暴力枚举栅栏的最终状态,用并查集维护连通性,对于内部有空洞的情况搜索一发即可。

首先这道题码量比较大,其次很难想到暴力枚举 (第一感是状压 qwq),还有就是这个 多边形 的限制比较多,容易算错情况。总而言之这是一道比较综合的题。放在 E 确实比较坑。

#include<bits/stdc++.h> #define fi first #define se second #define vi vector<int> #define db double #define inf 0x3f3f3f3f #define ll long long #define pii pair<int,int> using namespace std; int s[5][5],t[5][5],fa[16],vis[5][5],res,cnt; int dx[4]={-1,0,1,0},dy[4]={0,1,0,-1}; int find(int x) { return fa[x]==x?x:fa[x]=find(fa[x]); } int ca(int j,int k) { return (j-1)*4+k-1; } void add(int x,int y) { if(find(x)!=find(y)) { fa[fa[x]]=fa[y]; cnt--; } } bool dfs(int i,int j) { if(i<1||i>4||j<1||j>4) return 1; if(vis[i][j]) return 0; vis[i][j]=1; for(int l=0;l<4;l++) { int i2=i+dx[l],j2=j+dy[l]; if(t[i2][j2]==0&&dfs(i2,j2)) return 1; } return 0; } int main() { for(int i=1;i<=4;i++) { for(int j=1;j<=4;j++) { cin>>s[i][j]; } } for(int i=0;i<1<<16;i++) { for(int j=0;j<16;j++) fa[j]=j; int flg=1; for(int j=1;j<=4;j++) { for(int k=1;k<=4;k++) { int l=ca(j,k); t[j][k]=i>>l&1; if(s[j][k]>t[j][k]) { flg=0; } } } if(flg==0) continue; cnt=0; for(int j=1;j<=4;j++) { for(int k=1;k<=4;k++) { if(t[j][k]==0) continue; cnt++; if(t[j][k-1]) add(ca(j,k),ca(j,k-1)); if(t[j-1][k]) add(ca(j-1,k),ca(j,k)); } } if(cnt!=1) continue; //必须是一个多边形 for(int j=1;j<=4;j++) { for(int k=1;k<=4;k++) { //搜索 memset(vis,0,sizeof(vis)); if(t[j][k]==0&&!dfs(j,k)) { flg=0; } } } if(flg==0) continue; res++; } cout<<res; }

G - Propagation

比较套路的分块题。

维护三个标记:

  1. 这个点对相邻点的修改标记
  2. 这个点的真实数字
  3. 这个点当前处理完的最后一个标记的编号

时间复杂度 O ( q m ) O(q\sqrt{m}) O(qm )

#include<bits/stdc++.h> #define fi first #define se second #define vi vector<int> #define db double #define inf 0x3f3f3f3f #define ll long long #define pii pair<int,int> using namespace std; const int Maxn=2e5+5; int n,m,q,B,deg[Maxn],now[Maxn],c1[Maxn],c2[Maxn],c3[Maxn]; pii e[Maxn]; vector<int> g[Maxn]; vector<int> g2[Maxn]; int main() { cin>>n>>m>>q; B=sqrt(n); for(int i=1;i<=m;i++) { int u,v; cin>>u>>v; deg[u]++; deg[v]++; e[i].fi=u; e[i].se=v; } for(int i=1;i<=m;i++) { int u=e[i].fi,v=e[i].se; //大 -> 大 if(deg[u]>B&&deg[v]>B) { g2[u].push_back(v); g2[v].push_back(u); } //小 -> 小 or 小 -> 大 else { g[u].push_back(v); g[v].push_back(u); } } for(int i=1;i<=n;i++) c1[i]=i; for(int i=1;i<=q;i++) { int x; cin>>x; if(deg[x]<=B) { for(auto y:g[x]) { if(c2[y]&&c3[y]>now[x]) { now[x]=c3[y]; c1[x]=c2[y]; } } for(auto y:g[x]) { c1[y]=c1[x]; now[y]=i; } } else { for(auto y:g2[x]) { if(c2[y]&&c3[y]>now[x]) { now[x]=c3[y]; c1[x]=c2[y]; } } c2[x]=c1[x]; c3[x]=i; } } for(int x=1;x<=n;x++) { if(deg[x]<=B) { for(auto y:g[x]) { if(c2[y]&&c3[y]>now[x]) { now[x]=c3[y]; c1[x]=c2[y]; } } } else { for(auto y:g2[x]) { if(c2[y]&&c3[y]>now[x]) { now[x]=c3[y]; c1[x]=c2[y]; } } } printf("%d ",c1[x]); } }

F - Cleaning Robot

这题很神啊。


__EOF__

本文作者仰望星空的蚂蚁
本文链接https://www.cnblogs.com/cqbzly/p/17530243.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   仰望星空的蚂蚁  阅读(25)  评论(0编辑  收藏  举报  
点击右上角即可分享
微信分享提示