ABC375

卡布叻_周深發表於2024-10-13

前言

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");
}