ARC130 题解

A. Remove One Character

容易发现 \(i,j\) 产生贡献当且仅当 \(\forall k\in[i,j],a_i=a_k=a_j\),于是对于每个连通块分别计算贡献即可。

#include<bits/stdc++.h>
using namespace std;
#define inf 1e9
const int maxn=2e5+10;
const int mod=1e9+7;
inline int read(){
	int x=0,f=1;char c=getchar();
	while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
	while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+c-'0';c=getchar();}
	return x*f;
}
int n,m;string s;
long long ans;
int main(){
	n=read();cin>>s;
	int cnt=1,pos=0;
	for(int i=1;i<n;i++){
		if(s[pos]!=s[i])pos=i,cnt=0;
		ans+=cnt;++cnt;
	}printf("%lld\n",ans);
	return 0;
}

B. Colorful Lines

首先离散化,考虑时光倒流计算贡献,那么若这一行/列已经被染过色则无贡献,否则贡献为行/列长度减去另一方向上已有直线个数。

#include<bits/stdc++.h>
using namespace std;
#define inf 1e9
const int maxn=3e5+10;
const int mod=1e9+7;
inline int read(){
	int x=0,f=1;char c=getchar();
	while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
	while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+c-'0';c=getchar();}
	return x*f;
}
int h,w,c,Q,b[2][maxn],C[2],vis[2][maxn];
long long ans[maxn];
struct query{int tp,id,col;}q[maxn];
int main(){
	h=read(),w=read(),c=read(),Q=read();
	for(int i=1,tp,id,col;i<=Q;i++){
		tp=read()-1,id=read(),col=read();
		q[i]=(query){tp,id,col};b[tp][++C[tp]]=id;
	}sort(b[0]+1,b[0]+1+C[0]);
	C[0]=unique(b[0]+1,b[0]+1+C[0])-b[0]-1;
	sort(b[1]+1,b[1]+1+C[1]);
	C[1]=unique(b[1]+1,b[1]+1+C[1])-b[1]-1;
	for(int i=1;i<=Q;i++){
		int tp=q[i].tp,id=q[i].id;
		q[i].id=lower_bound(b[tp]+1,b[tp]+1+C[tp],id)-b[tp];
	}C[0]=C[1]=0;
	for(int i=Q;i>=1;i--){
		int tp=q[i].tp,id=q[i].id,col=q[i].col;
		if(vis[tp][id])continue;vis[tp][id]=1;
		ans[col]+=(tp?h:w)-C[tp^1];++C[tp];
	}
	for(int i=1;i<=c;i++)
		printf("%lld ",ans[i]);puts("");
    return 0;
}

C. Digit Sum Minimization

考场上不会!其实是很简单的题目啊

首先我们自然的相法就是拼出最多的进位,这显然是正确的,我们想拼出尽量多的十,然后接尽量多的九。

仔细观察,其实我们只用拼出一个十,后面都拼九就可以,也就是 \(s_0+t_0\geqslant 10\)\(i>1,s_i+t_i\geqslant 9\)

由于只有 \(s_0\)\(t_0\) 是特殊的,于是考虑枚举这两个数就做完了。代码借鉴 He_Ren

#include<bits/stdc++.h>
using namespace std;
#define inf 1e9
const int maxn=2e5+10;
const int mod=1e9+7;
inline int read(){
	int x=0,f=1;char c=getchar();
	while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
	while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+c-'0';c=getchar();}
	return x*f;
}
#define str string
str s,t;
int n,m,cs[10],ct[10],ts[10],tt[10];
#define pip pair<int,pair<str,str>>
#define mkp make_pair
#define fi first
#define se second
inline pip calc(int a,int b){
	for(int i=1;i<=9;i++)ts[i]=cs[i],tt[i]=ct[i];
	string S(1,a+'0'),T(1,b+'0');int res=1;
	for(int i=1;i<=9;i++)
		for(int j=1;j<=9;j++)if(i+j>=9){
			int c=min(ts[i],tt[j]);
			ts[i]-=c;tt[j]-=c;res+=c;
			S+=str(c,i+'0'),T+=str(c,j+'0');
		}
	res+=max(ts[9],tt[9]);
	for(int i=9;i>=1;i--)
		S+=str(ts[i],i+'0'),T+=str(tt[i],i+'0');
	reverse(S.begin(),S.end());
	reverse(T.begin(),T.end());
	return mkp(res,mkp(S,T));
} 
int main(){
	cin>>s>>t;
	pip ans=mkp(0,mkp(s,t));
	for(char c:s)cs[c-'0']++;
	for(char c:t)ct[c-'0']++;
	for(int i=1;i<=9;i++)
		for(int j=1;j<=9;j++)
			if(cs[i]&&ct[j]&&i+j>=10){
				cs[i]--,ct[j]--;
				ans=max(ans,calc(i,j));
				cs[i]++,ct[j]++;
			}
	cout<<ans.se.fi<<endl<<ans.se.se;
	return 0;
}

D. Zigzag Tree

简单题。肯定考虑树形背包,\(dp_{i,j,0/1}\) 表示 \(i\) 子树内,\(P_i\) 的排名为 \(j\)\(P_i>P_{son_i}\) 的方案数。

合并的时候,可以枚举子树在 \(P_i\) 以前的个数,然后前缀和优化,时间 \(O(n^2)\)

#include<bits/stdc++.h>
using namespace std;
#define inf 1e9
const int maxn=2e5+10;
const int mod=998244353;
inline int read(){
	int x=0,f=1;char c=getchar();
	while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
	while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+c-'0';c=getchar();}
	return x*f;
}
const int N=3e3+5;
int n,m,dp[N][N][2],S[N][N][2],ans,sz[N],f[N],g[N];
int beg[N],nex[N<<1],to[N<<1],e;
int fac[N<<1],ifc[N<<1],inv[N<<1];
inline int com(int x,int y){return 1ll*fac[x]*ifc[y]%mod*ifc[x-y]%mod;}
inline int Coef(int x,int y){return com(x+y,x);}
inline void add(int x,int y){
	++e;nex[e]=beg[x];beg[x]=e;to[e]=y;
	++e;nex[e]=beg[y];beg[y]=e;to[e]=x;
}
inline void Add(int &x,int y){x=(x+y>=mod?x+y-mod:x+y);}
inline void dfs(int x,int fa){
	sz[x]=1;dp[x][1][0]=dp[x][1][1]=1;
	for(int i=beg[x];i;i=nex[i]){
		int t=to[i];if(t==fa)continue;dfs(t,x);
		for(int a=1;a<=sz[x];a++){
			f[a]=dp[x][a][0],dp[x][a][0]=0;
			g[a]=dp[x][a][1],dp[x][a][1]=0;
		}
		for(int a=1;a<=sz[x];a++)
			for(int b=0;b<=sz[t];b++){
				int coef=1ll*com(a+b-1,b)*com(sz[x]+sz[t]-a-b,sz[t]-b)%mod;
				Add(dp[x][a+b][1],1ll*g[a]*coef%mod*S[t][b][0]%mod);
				Add(dp[x][a+b][0],1ll*f[a]*coef%mod*(S[t][sz[t]][1]-S[t][b][1]+mod)%mod);
			}
		sz[x]+=sz[t];
	}
	for(int i=1;i<=n;i++)f[i]=g[i]=0;
	for(int i=1;i<=n;i++){
		S[x][i][0]=S[x][i-1][0],S[x][i][1]=S[x][i-1][1];
		Add(S[x][i][0],dp[x][i][0]),Add(S[x][i][1],dp[x][i][1]);
	}
}
int main(){
	n=read();
	for(int i=1,x,y;i<n;i++)
		x=read(),y=read(),add(x,y);
	inv[1]=fac[0]=ifc[0]=1;
	for(int i=2;i<=n+n;i++)
		inv[i]=1ll*(mod-mod/i)*inv[mod%i]%mod;
	for(int i=1;i<=n+n;i++)
		fac[i]=1ll*fac[i-1]*i%mod;
	for(int i=1;i<=n+n;i++)
		ifc[i]=1ll*ifc[i-1]*inv[i]%mod;
	dfs(1,0);
	for(int i=1;i<=n;i++)
		ans=(0ll+ans+dp[1][i][0]+dp[1][i][1])%mod;
	printf("%d\n",ans);
	return 0;
}

E. Increasing Minimum

对着 Froggay 的代码阅读理解的,没太懂细节,大概讲一下吧。

首先发现对于任意解其大小关系不变,于是只用使我们的构造解中的相等关系尽量多即为最优解。

我们不妨假设任意时刻,\(\max\limits_{i,j} |a_i-a_j|\leqslant 1\),我们可以假设没有限制的位置为当前最小值。

整体加一当且仅当最近不重不漏地出现了每个出现过的元素,于是无解就好判断了。

最后再取那个当前的 \(\max a_i\),再一个一个模拟减回去即可。

#include<bits/stdc++.h>
using namespace std;
#define inf 1e9
const int maxn=3e5+10;
const int mod=1e9+7;
inline int read(){
	int x=0,f=1;char c=getchar();
	while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
	while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+c-'0';c=getchar();}
	return x*f;
}
int n,m,a[maxn],ans[maxn],las[maxn],cnt,lp,dep[maxn];
int main(){
	n=read(),m=read();
	for(int i=1;i<=m;i++){
		a[i]=read();
		if(!las[a[i]])++cnt;
		lp=max(lp,las[a[i]]);
		las[a[i]]=i;
		if(i-lp==cnt)dep[i]=dep[lp]+1;
		else dep[i]=inf+1;
	}int Mn=inf,pos=-1;
	for(int i=lp;i<=m;i++)
		if(dep[i]<=Mn)Mn=dep[i],pos=i;
	if(pos==-1)
		return puts("-1")&0;
	for(int i=1;i<=n;i++)ans[i]=Mn+1;
	for(int i=1;i<=pos;i++)ans[a[i]]--;
	for(int i=1;i<=n;i++)
		printf("%d ",ans[i]);puts("");
	return 0;
}

F. Replace by Average

凸包?鸽了鸽了

posted @ 2022-03-30 05:47  syzf2222  阅读(189)  评论(0编辑  收藏  举报