【比赛记录】2025CSP-S模拟赛51

A B C D Sum Rank
100 9 54 - 163 11/24

A. 算术

列个表格:

\(a_i\to\)
\(a_j\downarrow\)
\(\le0\) \(1\) \(>1\)
\(\le0\)
\(1\)
\(>1\)

记录当前 \(=1\)\(>1\)\(\ge1\) 的数量即可。

Code
#include<bits/stdc++.h>
#define ll long long
#define il inline
using namespace std;
namespace asbt{
const int maxn=1e6+5;
int n,cntge1,cnte1,cntg1;
ll a[maxn];
int main(){
	ios::sync_with_stdio(0),cin.tie(0);
	cin>>n;
	ll ans=0;
	for(int i=1;i<=n;i++){
		cin>>a[i];
		if(a[i]<=0){
			ans+=cntge1;
		}else if(a[i]==1){
			ans+=i-1;
			cnte1++,cntge1++;
		}else{
			ans+=i-1-cntg1;
			cntg1++,cntge1++;
		}
//		cout<<ans<<'\n';
	}
	cout<<ans;
	return 0;
}
}
int main(){return asbt::main();}

B. 刷墙

区间 DP。设 \(f_{l,r}\) 表示区间 \([l,r]\) 的最大颜色数量。枚举 \(k\in[l,r)\),考虑优先染一个包含了 \([k,k+1]\) 的颜色,然后再递归 \([l,k]\)\([k+1,r]\) 的子问题。二维前缀和查一下即可。

Code
#include<bits/stdc++.h>
#define il inline
#define lwrb lower_bound
using namespace std;
namespace asbt{
int n,ll[305],rr[305],lsh[605],tot,f[605][605],s[605][605];
il int get(int l1,int l2,int r1,int r2){
	return s[l2][r2]-s[l1-1][r2]-s[l2][r1-1]+s[l1-1][r1-1];
}
int main(){
	ios::sync_with_stdio(0),cin.tie(0);
	cin>>n;
	for(int i=1;i<=n;i++){
		cin>>ll[i]>>rr[i];
		lsh[++tot]=ll[i];
		lsh[++tot]=rr[i];
	}
	sort(lsh+1,lsh+tot+1);
	tot=unique(lsh+1,lsh+tot+1)-lsh-1;
	for(int i=1;i<=n;i++){
		s[lwrb(lsh+1,lsh+tot+1,ll[i])-lsh][lwrb(lsh+1,lsh+tot+1,rr[i])-lsh]++;
	}
	for(int i=1;i<=tot;i++){
		for(int j=1;j<=tot;j++){
			s[i][j]+=s[i-1][j]+s[i][j-1]-s[i-1][j-1];
		}
	}
	for(int len=2;len<=tot;len++){
		for(int l=1,r=len;r<=tot;l++,r++){
			for(int p=l;p<r;p++){
				f[l][r]=max(f[l][r],f[l][p]+f[p+1][r]+(get(l,p,p+1,r)>0));
			}
		}
	}
	cout<<f[1][tot];
	return 0;
}
}
int main(){return asbt::main();}

C. 重复

我们要找的实际上是一段形如 AABCAB 的字符串,不妨考虑枚举第二个 A 的开头 \(i\) 和第三个 A 的开头 \(j\)。对于以它们开头的最长公共前缀,对第一个 B 的开头位置的贡献是这样的(先不考虑第一个 A 的限制):

image

于是我们预处理最长公共前缀,然后对于每一个 \(i\) 去做两遍前缀和即可。至于第一个 A 的限制,再用哈希判断一下就好了。时间复杂度 \(O(n^2)\)

Code
#include<bits/stdc++.h>
#define ll long long
#define il inline
#define ull unsigned ll
using namespace std;
namespace asbt{
const int maxn=5e3+5;
const ull bas1=13331;
const ll bas2=13327,mod2=1e9+7;
int n,len[maxn][maxn];
ull ha1[maxn],pw1[maxn];
ll ha2[maxn],pw2[maxn],cnt[maxn];
string s;
int main(){
	ios::sync_with_stdio(0),cin.tie(0);
	cin>>s;
	n=s.size(),s=" "+s;
	pw1[0]=pw2[0]=1;
	for(int i=1;i<=n;i++){
		pw1[i]=pw1[i-1]*bas1;
		pw2[i]=pw2[i-1]*bas2%mod2;
		ha1[i]=ha1[i-1]*bas1+s[i];
		ha2[i]=(ha2[i-1]*bas2+s[i])%mod2;
	}
	for(int i=n;i;i--){
		for(int j=n;j>i;j--){
			if(s[i]==s[j]){
				len[i][j]=min(len[i+1][j+1]+1,j-i-1);
			}
		}
	}
	ll ans=0;
	for(int i=1;i<=n;i++){
		for(int j=1;j<=n;j++){
			cnt[j]=0;
		}
		for(int j=i+1;j<=n;j++){
			cnt[len[i][j]]++;
		}
		for(int j=n;j;j--){
			cnt[j]+=cnt[j+1];
		}
		for(int j=n;j;j--){
			cnt[j]+=cnt[j+1];
		}
		for(int j=1;j<i;j++){
			if(ha1[i+j-1]-ha1[i-1]==(ha1[i-1]-ha1[i-j-1])*pw1[j]&&(ha2[i+j-1]-ha2[i-1]+mod2)%mod2==(ha2[i-1]-ha2[i-j-1]+mod2)*pw2[j]%mod2){
				ans+=cnt[j+1];
			}
		}
	}
	cout<<ans;
	return 0;
}
}
int main(){return asbt::main();}

D. 公交

首先将题意进行一个转化。考虑我们一开始只有一个点,即树根,然后一层层地往下走,选择 \(u\) 能使答案减小 \(sz_u\)。因此我们要做的就是一个长链剖分,取前 \(k\) 大的即可。

考虑换根,发现发生变化的长链只有 \(O(1)\) 条,于是用 multiset 维护即可。时间复杂度 \(O(n\log n)\)

标签:implementation

Code
#include<bits/stdc++.h>
#define int long long
#define il inline
#define pb push_back
using namespace std;
namespace asbt{
const int maxn=2e5+5;
int n,m,a[maxn],sz[maxn],dis[maxn];
int mx1[maxn],mx2[maxn],hes[maxn];
int ans[maxn],sum;
bool top[maxn];
vector<int> e[maxn];
multiset<int> s1,s2;
il void insert(int x){
	if(!x){
		return ;
	}
	sum+=x,s1.insert(x);
	if(s1.size()>m){
		sum-=*s1.begin();
		s2.insert(*s1.begin());
		s1.erase(s1.begin());
	}
}
il void erase(int x){
	if(!x){
		return ;
	}
	if(s1.find(x)!=s1.end()){
		sum-=x,s1.erase(s1.find(x));
		if(s2.size()){
			sum+=*s2.rbegin();
			s1.insert(*s2.rbegin());
			s2.erase(prev(s2.end()));
		}
	}else{
		s2.erase(s2.find(x));
	}
}
il void dfs1(int u,int fa){
	sz[u]=a[u];
	for(int v:e[u]){
		if(v==fa){
			continue;
		}
		dfs1(v,u);
		sz[u]+=sz[v];
		dis[u]+=dis[v]+sz[v];
		if(mx1[v]+sz[v]>=mx1[u]){
			mx2[u]=mx1[u],mx1[u]=mx1[v]+sz[v];
			top[hes[u]]=0,top[v]=1,hes[u]=v;
		}else if(mx1[v]+sz[v]>=mx2[u]){
			mx2[u]=mx1[v]+sz[v];
		}
	}
}
il void dfs2(int u,int fa){
	if(!top[u]){
		insert(mx1[u]+sz[u]);
	}
	for(int v:e[u]){
		if(v==fa){
			continue;
		}
		dis[v]=dis[u]-sz[v]*2+sz[1];
		dfs2(v,u);
	}
}
il void dfs3(int u,int fa){
//	cout<<u<<":\n";
//	cout<<s1.size()<<' '<<s2.size()<<'\n';
//	for(int x:s1){
//		cout<<x<<' ';
//	}
//	cout<<'\n';
//	for(int x:s2){
//		cout<<x<<' ';
//	}
//	cout<<'\n';
	for(int v:e[u]){
		if(v==fa){
			continue;
		}
		int flag=0;
		int mx1v=mx1[v],mx2v=mx2[v];
		if(top[v]){
			if(mx1[v]>mx2[u]+sz[1]-sz[v]){
				flag=1;
				erase(mx1[u]+sz[1]);
				erase(mx2[u]);
				insert(mx1[v]+sz[1]);
				insert(mx2[u]+sz[1]-sz[v]);
				if(mx2[u]+sz[1]-sz[v]>mx2[v]){
					mx2[v]=mx2[u]+sz[1]-sz[v];
				}
			}else{
				flag=2;
				erase(mx1[u]+sz[1]);
				erase(mx2[u]);
				insert(2*sz[1]-sz[v]+mx2[u]);
				insert(mx1[v]);
				mx2[v]=mx1[v],mx1[v]=mx2[u]+sz[1]-sz[v];
				top[hes[v]]=0;
			}
		}else{
			flag=3;
			erase(mx1[v]+sz[v]);
			erase(mx1[u]+sz[1]);
			insert(mx1[v]);
			insert(2*sz[1]-sz[v]+mx1[u]);
			mx2[v]=mx1[v];
			mx1[v]=mx1[u]+sz[1]-sz[v];
			top[hes[v]]=0;
		}
		ans[v]=dis[v]-sum+sz[1];
		dfs3(v,u);
		mx1[v]=mx1v,mx2[v]=mx2v;
		switch(flag){
			case 1:{
				insert(mx1[u]+sz[1]);
				insert(mx2[u]);
				erase(mx1[v]+sz[1]);
				erase(mx2[u]+sz[1]-sz[v]);
				break;
			}
			case 2:{
				insert(mx1[u]+sz[1]);
				insert(mx2[u]);
				erase(2*sz[1]-sz[v]+mx2[u]);
				erase(mx1[v]);
				top[hes[v]]=1;
				break;
			}
			default:{
				insert(mx1[v]+sz[v]);
				insert(mx1[u]+sz[1]);
				erase(mx1[v]);
				erase(2*sz[1]-sz[v]+mx1[u]);
				top[hes[v]]=1;
				break;
			}
		}
	}
}
int main(){
	ios::sync_with_stdio(0),cin.tie(0);
	cin>>n>>m;
	for(int i=1;i<=n;i++){
		cin>>a[i];
	}
	for(int i=1,u,v;i<n;i++){
		cin>>u>>v;
		e[u].pb(v),e[v].pb(u);
	}
	dfs1(1,0),dfs2(1,0);
	ans[1]=dis[1]-sum+sz[1];
//	for(int i=1;i<=n;i++){
//		cout<<dis[i]<<' ';
//	}
//	cout<<'\n';
//	for(int i=1;i<=n;i++){
//		cout<<sz[i]<<' ';
//	}
//	cout<<'\n';
	dfs3(1,0);
	for(int i=1;i<=n;i++){
		cout<<ans[i]<<' ';
	}
	return 0;
}
}
signed main(){return asbt::main();}
posted @ 2025-09-21 21:42  zhangxy__hp  阅读(36)  评论(0)    收藏  举报