ABC245 简要题解

A

由题意模拟。

int a,b,c,d;
signed main(){
	a=read(),b=read(),c=read(),d=read();
	if(a<c||(a==c&&b<=d)) puts("Takahashi");
	else puts("Aoki");
	return 0;
}

B

由题意模拟。

int n,a[2005];
signed main(){
	n=read();
	for(rg int i=1;i<=n;++i) a[i]=read();
	sort(a+1,a+1+n); n=unique(a+1,a+1+n)-a-1;
	if(a[1]>0) return 0*printf("0\n");
	for(rg int i=2;i<=n;++i) if(a[i]>a[i-1]+1) return 0*printf("%d\n",a[i-1]+1);
	printf("%d\n",a[n]+1);
	return 0;
}

C

\(f_{i,0/1}\) 表示第 \(i\) 的数为 \(a_i\)\(b_i\) 时前缀 \(i\) 有无合法方案,枚举并转移即可。

int n,K,a[200005][2];
bool f[200005][2];
signed main(){
	n=read(),K=read(); f[1][0]=f[1][1]=1;
	for(rg int i=1;i<=n;++i) a[i][0]=read();
	for(rg int i=1;i<=n;++i) a[i][1]=read();
	for(rg int i=2;i<=n;++i) for(rg int j=0;j<2;++j) for(rg int k=0;k<2;++k) if(abs(a[i][j]-a[i-1][k])<=K) f[i][j]|=f[i-1][k];
	puts((f[n][0]||f[n][1])?"Yes":"No");
	return 0;
}

D

两种做法,第一种做法是找个大于 \(10^{10}\) 的 NTT 模数然后跑多项式求逆,注意过程中要开 __int128;第二种做法直接递推(题目保证 \([x^n]A(x)\ne 0\)):

\[[x^i]B(x)=\dfrac{[x^{n+i}]C(x)-\sum_{i<j\leq \min(m,n+i)}[x^j]B(x)\times[x^{n+i-j}]A(x)}{[x^n]A(x)} \]

int n,m,A[200005],C[200005],B[200005];
signed main(){
	n=read(),m=read();
	for(rg int i=0;i<=n;++i) A[i]=read();
	for(rg int i=0;i<=n+m;++i) C[i]=read();
	B[m]=C[n+m]/A[n];
	for(rg int i=m-1;~i;--i){
		int now=C[n+i];
		for(rg int j=i+1;j<=m&&j<=n+i;++j) now-=A[n+i-j]*B[j];
		B[i]=now/A[n];
	}
	for(rg int i=0;i<=m;++i) printf("%d ",B[i]);
	return 0;
}

哪个 sb 一开始看成了保证 \([x^0]A(x)\ne 0\) 还吃了几发罚时?哦,原来就是我啊。


E

贪心,按第一维大小降序考虑每个物品放在哪个盒子中,设当前考虑到 \((a,b)\),那么将它放在满足 \(c\geq a,d\geq b\)\(d\) 最小的盒子中最优,找不到这样的盒子即无解。

可以用扰动法证明。

注意到可能有重复的盒子,要用 multiset 维护。

int n,m;
pii a[200005],b[200005];
multiset<pii> s;
signed main(){
	n=read(),m=read();
	for(rg int i=1;i<=n;++i) a[i].fi=read();
	for(rg int i=1;i<=n;++i) a[i].se=read();
	for(rg int i=1;i<=m;++i) b[i].fi=read();
	for(rg int i=1;i<=m;++i) b[i].se=read();
	sort(a+1,a+1+n),sort(b+1,b+1+m);
	for(rg int i=n,j=m;i;--i){
		while(j>=1&&b[j].fi>=a[i].fi) s.insert(mkp(b[j].se,b[j].fi)),--j;
		auto k=s.lower_bound(mkp(a[i].se,a[i].fi));
		if(k==s.end()) return 0*puts("No");
		s.erase(k);
	}
	puts("Yes");
	return 0;
}

F

tarjan 板题,节点 \(i\) 若能走到一个大小大于 \(1\) 的 scc 就可以在这个 scc 里绕圈圈,缩点后 dp 即可。

vector<int> e[200005];
int n,m,u[200005],v[200005],ans;
int dfn[200005],low[200005],tot,cnts,col[200005],st[200005],top,siz[200005];
bool vis[200005],f[200005];
void dfs(int x){
	dfn[x]=low[x]=++tot,st[++top]=x,vis[x]=1;
	for(int y:e[x]){
		if(!dfn[y]) dfs(y),low[x]=min(low[x],low[y]);
		else if(vis[y]) low[x]=min(low[x],dfn[y]);
	}
	if(dfn[x]==low[x]){
		++cnts; int tmp;
		do{ tmp=st[top--],vis[tmp]=0,++siz[cnts],col[tmp]=cnts;
		}while(x!=tmp);
	}
}
bool dp(int x){
	if(vis[x]) return f[x];
	f[x]=(siz[x]>1); vis[x]=1;
	for(int y:e[x]) f[x]|=dp(y);
	return f[x];
}
signed main(){
	n=read(),m=read();
	for(rg int i=1;i<=m;++i) u[i]=read(),v[i]=read(),e[u[i]].epb(v[i]);
	for(rg int i=1;i<=n;++i) if(!dfn[i]) dfs(i);
	for(rg int i=1;i<=n;++i) e[i].clear(),vis[i]=0;
	for(rg int i=1;i<=m;++i) if(col[u[i]]!=col[v[i]]) e[col[u[i]]].epb(col[v[i]]);
	for(rg int i=1;i<=cnts;++i) if(!vis[i]) dp(i);
	for(rg int i=1;i<=cnts;++i) if(f[i]) ans+=siz[i];
	printf("%d\n",ans);
	return 0;
}

G

若没有要求不同国家,将所有受欢迎的人扔到队列里跑多源最短路即可;加上了这个要求,那么维护最短路和次短路即可(最短路和次短路的来源国家要不同)。

int n,m,k,l,cnt[100005],a[100005];
vector<edge> e[100005];
pair<ll,int> d[100005][2];
priority_queue<pair<ll,pii >> q;
inline pair<ll,pii> mkq(ll a,int b,int c){ return mkp(a,mkp(b,c)); }
signed main(){
	n=read(),m=read(),k=read(),l=read();
	for(rg int i=1;i<=n;++i) a[i]=read(),d[i][0].fi=d[i][1].fi=inf;
	for(rg int i=1,u;i<=l;++i) u=read(),q.push(mkq(0ll,u,a[u]));
	for(rg int i=1,u,v,w;i<=m;++i) u=read(),v=read(),w=read(),e[u].epb(edge(v,w)),e[v].epb(edge(u,w));
	while(!q.empty()){
		const ll dis=-q.top().fi; const int x=q.top().se.fi,ax=q.top().se.se; q.pop();
		if(cnt[x]==2) continue;
		bool fla=0;
		for(rg int i=0;i<cnt[x];++i) if(d[x][i].se==ax) fla=1;
		if(fla) continue;
		d[x][cnt[x]++]=mkp(dis,ax);
		for(edge i:e[x]) q.push(mkq(-dis-i.v,i.to,ax));
	}
	for(rg int i=1;i<=n;++i){
		if(d[i][0].se==a[i]) printf("%lld ",(d[i][1].fi==inf)?-1:d[i][1].fi);
		else printf("%lld ",(d[i][0].fi==inf)?-1:d[i][0].fi);
	}
	return 0;
}

Ex

咕咕咕

posted @ 2022-03-26 23:05  Legitimity  阅读(64)  评论(0编辑  收藏  举报