ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

ARC130 题解

2022-03-30 06:00:06  阅读:204  来源: 互联网

标签:const ARC130 int 题解 while 1e9 define getchar


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

凸包?鸽了鸽了

标签:const,ARC130,int,题解,while,1e9,define,getchar
来源: https://www.cnblogs.com/syzf2222/p/16074740.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有