ABC375
前言
F、G 没时间写了,主要是 C 太唐了,甚至没想到转两遍的只需要把转一遍的循环两边就行了,浪费太多时间,D 因为 C++20 特殊性质 CE 了一发,E 数组开小吃了一发罚时。
A、B 没啥好说的从 C 开始吧。
C - Spiral Rotation
发现就是从歪往里数第多少层就是顺时针转多少圈,由此 \(\mod 4\) 转就行了。
点击查看代码
#include<bits/stdc++.h>
#define ll long long
#define endl '\n'
#define sort stable_sort
using namespace std;
const int N=3010;
template<typename Tp> inline void read(Tp&x)
{
x=0;register bool z=true;
register char c=getchar_unlocked();
for(;!isdigit(c);c=getchar_unlocked()) if(c=='-') z=0;
for(;isdigit(c);c=getchar_unlocked()) x=(x<<1)+(x<<3)+(c^48);
x=(z?x:~x+1);
}
template<typename T,typename ...Tp> inline void read(T &x,Tp &...y){read(x);read(y...);}
template<typename Tp> inline void wt(Tp x){if(x>9)wt(x/10);putchar_unlocked((x%10)+'0');}
template<typename Tp> inline void write(Tp x){if(x<0)putchar_unlocked('-'),x=~x+1;wt(x);}
template<typename T,typename ...Tp> inline void write(T x,Tp ...y){write(x);putchar_unlocked(' ');write(y...);}
int n;
char a[N][N],b[N][N];
signed main()
{
read(n);
for(int i=1;i<=n;i++) for(int j=1;j<=n;j++)
{
a[i][j]=getchar_unlocked();
while(a[i][j]!='.'&&a[i][j]!='#') a[i][j]=getchar_unlocked();
}
for(int i=1;i<=n/2;i++)
{
int x=i%4;
if(x==1)
{
for(int j=i;j<=n-i+1;j++)
{
b[i][j]=a[n+1-j][i];
b[j][i]=a[n+1-i][j];
b[n-i+1][j]=a[n+1-j][n+1-i];
b[j][n-i+1]=a[i][j];
}
for(int j=i;j<=n-i+1;j++)
{
a[i][j]=b[i][j];
a[j][i]=b[j][i];
a[n-i+1][j]=b[n-i+1][j];
a[j][n-i+1]=b[j][n-i+1];
}
}
else if(x==2)
{
for(int o=1;o<=2;o++)
{
for(int j=i;j<=n-i+1;j++)
{
b[i][j]=a[n+1-j][i];
b[j][i]=a[n+1-i][j];
b[n-i+1][j]=a[n+1-j][n+1-i];
b[j][n-i+1]=a[i][j];
}
for(int j=i;j<=n-i+1;j++)
{
a[i][j]=b[i][j];
a[j][i]=b[j][i];
a[n-i+1][j]=b[n-i+1][j];
a[j][n-i+1]=b[j][n-i+1];
}
}
}
else if(x==3)
{
for(int o=1;o<=3;o++)
{
for(int j=i;j<=n-i+1;j++)
{
b[i][j]=a[n+1-j][i];
b[j][i]=a[n+1-i][j];
b[n-i+1][j]=a[n+1-j][n+1-i];
b[j][n-i+1]=a[i][j];
}
for(int j=i;j<=n-i+1;j++)
{
a[i][j]=b[i][j];
a[j][i]=b[j][i];
a[n-i+1][j]=b[n-i+1][j];
a[j][n-i+1]=b[j][n-i+1];
}
}
}
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++) putchar_unlocked(a[i][j]);
puts("");
}
}
D - ABA
开两个计数数组就行了,一个统计个数,一个统计位置之和即可。
点击查看代码
#include<bits/stdc++.h>
#define ll long long
#define endl '\n'
#define sort stable_sort
#define lowbit(x) (x&-x)
using namespace std;
const int N=2e5+10;
template<typename Tp> inline void read(Tp&x)
{
x=0;register bool z=true;
register char c=getchar_unlocked();
for(;!isdigit(c);c=getchar_unlocked()) if(c=='-') z=0;
for(;isdigit(c);c=getchar_unlocked()) x=(x<<1)+(x<<3)+(c^48);
x=(z?x:~x+1);
}
template<typename T,typename ...Tp> inline void read(T &x,Tp &...y){read(x);read(y...);}
template<typename Tp> inline void wt(Tp x){if(x>9)wt(x/10);putchar_unlocked((x%10)+'0');}
template<typename Tp> inline void write(Tp x){if(x<0)putchar_unlocked('-'),x=~x+1;wt(x);}
template<typename T,typename ...Tp> inline void write(T x,Tp ...y){write(x);putchar_unlocked(' ');write(y...);}
int n; ll c1[30],c2[30],ans;
char s[N];
signed main()
{
scanf("%s",s+1); n=strlen(s+1);
for(int i=1;i<=n;i++)
{
ans+=c1[s[i]-'A'+1]*(i-1)-c2[s[i]-'A'+1];
c1[s[i]-'A'+1]++,c2[s[i]-'A'+1]+=i;
}
write(ans);
}
E - 3 Team Division
\(f_{i,j,k,h}\) 表示到了第 \(i\) 位,各组人数分别为 \(j,k,h\) 时的答案最小值,只统计“转进来的”,不考虑“转出去的”从而避免重复计算,直接转移即可,复杂度错误,发现 \(j+k+h=i\) 从而省掉一维,可以滚动数组。
点击查看代码
#include<bits/stdc++.h>
#define ll long long
#define endl '\n'
#define sort stable_sort
using namespace std;
const int N=110,M=510;
template<typename Tp> inline void read(Tp&x)
{
x=0;register bool z=true;
register char c=getchar_unlocked();
for(;!isdigit(c);c=getchar_unlocked()) if(c=='-') z=0;
for(;isdigit(c);c=getchar_unlocked()) x=(x<<1)+(x<<3)+(c^48);
x=(z?x:~x+1);
}
template<typename T,typename ...Tp> inline void read(T &x,Tp &...y){read(x);read(y...);}
template<typename Tp> inline void wt(Tp x){if(x>9)wt(x/10);putchar_unlocked((x%10)+'0');}
template<typename Tp> inline void write(Tp x){if(x<0)putchar_unlocked('-'),x=~x+1;wt(x);}
template<typename T,typename ...Tp> inline void write(T x,Tp ...y){write(x);putchar_unlocked(' ');write(y...);}
int n,siz,a[N],b[N],sum[N],f[2][M][M];
signed main()
{
read(n);
for(int i=1;i<=n;i++) read(a[i],b[i]),sum[i]=sum[i-1]+b[i];
if(sum[n]%3) return puts("-1"),0; siz=sum[n]/3;
memset(f,0x3f,sizeof(f)); f[0][0][0]=0;
for(int i=1,x=1,y=0;i<=n;i++,x^=1,y^=1)
for(int j=0;j<=min(siz,sum[i]);j++) for(int k=0;k<=min(siz,sum[i]);k++)
{
int h=sum[i]-j-k; f[x][j][k]=0x3f3f3f3f;
if(j>=b[i]) f[x][j][k]=min(f[x][j][k],f[y][j-b[i]][k]+(a[i]!=1));
if(k>=b[i]) f[x][j][k]=min(f[x][j][k],f[y][j][k-b[i]]+(a[i]!=2));
if(h>=b[i]) f[x][j][k]=min(f[x][j][k],f[y][j][k]+(a[i]!=3));
}
write(f[n&1][siz][siz]>=0x3f3f3f3f?-1:f[n&1][siz][siz]);
}
F - Road Blocked
倒着加边,每次加边跑一遍 dijkstra 或 floyed 即可,因为 \(m\) 为 \(n^2\) 级别,所以 dijkstra 不堆优化,复杂度为 \(O(n^2)\),floyed 只更新以加进来的边为转移点的,单次也是 \(O(n^2)\)。
点击查看代码
#include<bits/stdc++.h>
#define ll long long
#define endl '\n'
#define sort stable_sort
using namespace std;
const int N=310,M=2e5+10;
template<typename Tp> inline void read(Tp&x)
{
x=0;register bool z=true;
register char c=getchar_unlocked();
for(;!isdigit(c);c=getchar_unlocked()) if(c=='-') z=0;
for(;isdigit(c);c=getchar_unlocked()) x=(x<<1)+(x<<3)+(c^48);
x=(z?x:~x+1);
}
template<typename T,typename ...Tp> inline void read(T &x,Tp &...y){read(x);read(y...);}
template<typename Tp> inline void wt(Tp x){if(x>9)wt(x/10);putchar_unlocked((x%10)+'0');}
template<typename Tp> inline void write(Tp x){if(x<0)putchar_unlocked('-'),x=~x+1;wt(x);}
template<typename T,typename ...Tp> inline void write(T x,Tp ...y){write(x);putchar_unlocked(' ');write(y...);}
int n,m,q; ll ans[M],dis[N][N]; bitset<N*N>vis;
struct aa {int x,y,z;}e[N*N]; struct bb {int op,x,y;}g[M];
signed main()
{
read(n,m,q); memset(dis,0x3f,sizeof(dis));
for(int i=1,x,y,z;i<=m;i++) read(x,y,z),e[i]={x,y,z};
for(int i=1,op,x,y;i<=q;i++)
read(op,x),(op&1)?(void)vis.set(x):read(y),g[i]={op,x,y};
for(int i=1,x,y;i<=m;i++) if(!vis[i])
dis[x][y]=dis[y][x]=min(dis[x=e[i].x][y=e[i].y],(ll)e[i].z);
for(int k=1;k<=n;k++) for(int i=1;i<=n;i++) for(int j=1;j<=n;j++)
dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);
for(int o=q,op,x,y,u,v;(op=g[o].op)&&(x=g[o].x)&&(y=g[o].y);o--)
{
if(op&1)
{
dis[u][v]=dis[v][u]=min(dis[u=e[x].x][v=e[x].y],(ll)e[x].z);
for(int i=1;i<=n;i++) for(int j=1;j<=n;j++)
dis[i][j]=min(dis[i][j],dis[i][u]+dis[u][j]);
for(int i=1;i<=n;i++) for(int j=1;j<=n;j++)
dis[i][j]=min(dis[i][j],dis[i][v]+dis[v][j]);
}
else ans[o]=(dis[x][y]==0x3f3f3f3f3f3f3f3f?-1:dis[x][y]);
}
for(int i=1;i<=q;i++) if(!(g[i].op&1)) write(ans[i]),puts("");
}
G - Road Blocked 2
删边最短路板子,把最短路 DAG 建出来,当成无向图求割边即可。
点击查看代码
#include<bits/stdc++.h>
#define ll long long
#define endl '\n'
#define sort stable_sort
#define pb push_back
#define mkp make_pair
#define fi first
#define se second
using namespace std;
const int N=2e5+10;
template<typename Tp> inline void read(Tp&x)
{
x=0;register bool z=true;
register char c=getchar_unlocked();
for(;!isdigit(c);c=getchar_unlocked()) if(c=='-') z=0;
for(;isdigit(c);c=getchar_unlocked()) x=(x<<1)+(x<<3)+(c^48);
x=(z?x:~x+1);
}
template<typename T,typename ...Tp> inline void read(T &x,Tp &...y){read(x);read(y...);}
template<typename Tp> inline void wt(Tp x){if(x>9)wt(x/10);putchar_unlocked((x%10)+'0');}
template<typename Tp> inline void write(Tp x){if(x<0)putchar_unlocked('-'),x=~x+1;wt(x);}
template<typename T,typename ...Tp> inline void write(T x,Tp ...y){write(x);putchar_unlocked(' ');write(y...);}
int n,m,tot,dfn[N],low[N],head[N],nxt[N<<1],to[N<<1],w[N<<1],id[N<<1];
ll dis[N]; bitset<N>vis,cut; vector<pair<int,int> >e[N],pre[N];
void add(int x,int y,int z,int i)
{nxt[++tot]=head[x],to[tot]=y,w[tot]=z,id[tot]=i,head[x]=tot;}
void dijkstra()
{
memset(dis,0x3f,sizeof(dis)),dis[1]=0;
priority_queue<pair<ll,int> >q; q.push(mkp(0,1));
while(!q.empty())
{
int x=q.top().se; q.pop();
if(vis[x]) continue; vis.set(x);
for(int i=head[x],y;y=to[i];i=nxt[i]) if(dis[y]>dis[x]+w[i])
dis[y]=dis[x]+w[i],q.push(mkp(-dis[y],y));
}
}
void dfs(int x)
{
if(vis[x]) return ; vis.set(x); for(auto y:pre[x])
dfs(y.fi),e[x].pb(y),e[y.fi].pb(mkp(x,y.se));
}
void build()
{
for(int x=1;x<=n;x++) for(int i=head[x],y;y=to[i];i=nxt[i])
if(dis[y]==dis[x]+w[i]) pre[y].pb(mkp(x,id[i]));
}
void tarjan(int x,int t)
{
dfn[x]=low[x]=++tot; for(auto y:e[x])
{
if(!dfn[y.fi])
{
tarjan(y.fi,x),low[x]=min(low[x],low[y.fi]);
cut[y.se]=(low[y.fi]>dfn[x]);
}
else if(y.fi!=t) low[x]=min(low[x],dfn[y.fi]);
}
}
signed main()
{
read(n,m);
for(int i=1,x,y,z;i<=m;i++) read(x,y,z),add(x,y,z,i),add(y,x,z,i);
dijkstra(),build(),vis.reset(),dfs(n),tot=0,tarjan(1,1);
for(int i=1;i<=m;i++) puts(cut[i]?"Yes":"No");
}