CF Round 997 题解合集

here.

C

考虑这样一种构造:

\[1,2,3,\cdots,n-1,n,1,2,3,\cdots,n-1,n \]

或者是:

\[1,2,3,\cdots,n-2,n-1,n,1,2,3,\cdots,n-2,n-1 \]

这里的 \(n\) 不是题面中的 \(n\)

但是经检查,这种构造会在 \(n=6\) 时死掉。

所以考虑特判 \(n=6\)

#include<bits/stdc++.h>
using namespace std;
int t,n;
signed main(){
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	cin>>t;
	while(t--){
		cin>>n;
		if(n==6){
			cout<<"1 1 2 3 1 2\n";
			continue;
		}
		for(int i=1;i<=n/2;i++){
			cout<<i<<' ';
		}
		if(n&1) cout<<n<<' ';
		for(int i=(n+1)/2+1;i<=n;i++){
			cout<<i-(n+1)/2<<' ';
		}
		cout<<'\n';
	}
	return 0;
}

D

看到值域 \(\le 10\),考虑枚举值域,将序列上的数转化为 \(-1,1\) 去做。

因为对合法的区间计数不太好做,所以考虑对不合法的区间计数。

注意到,对于每个不合法区间,都存在唯一一个 \(x\),使得令 \(a_i \le x,a_i=-1;a_i>x,a_i=1\) 时,区间和为 \(0\)

然后就做完了。

注意因为 \(x\) 限制是区间中出现过的数,所以每次加入前缀时需要考虑形成的区间中是否存在 \(x\)

复杂度 \(O(nv)\)

#include<bits/stdc++.h>
#define int long long
using namespace std;
int t,n,ans,sum[200005],a[200005],b[200005],cnt[4000005];
signed main(){
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	cin>>t;
	while(t--){
		cin>>n;
		for(int i=1;i<=n;i++){
			cin>>a[i];
		}
		for(int k=1;k<=10;k++){
			for(int i=1;i<=n;i++){
				b[i]=(a[i]<=k?-1:1);
				sum[i]=sum[i-1]+b[i];
			}
			int j=1;
			for(int i=1;i<=n;i++){
				if(a[i]==k){
					for(;j<=i;j++){
						cnt[sum[j-1]+n]++;
					}	
				}
				ans+=cnt[sum[i]+n];
			}
			for(int i=0;i<=2*n;i++){
				cnt[i]=0;
			}
		}
		ans=n*(n+1)/2-ans;
		cout<<ans<<'\n';
		ans=0;
	}
	return 0;
}

E

观察发现,集合 \(S\) 的最大值是 \(2n-1\),具体构造可以考虑建立一棵二叉广义线段树。

然后考虑对这类树状物计数。

首先考虑 \(m=0\) 的情况。

\(f_i\) 表示 \(n=i\) 时的答案,初始 \(f_1=1\),不难得到转移:

\[f_i=\sum_{j=1}^{n-1} f_jf_{i-j} \]

然后这个形式看起来很像卡特兰数,打表发现 \(f_i=H_{i-1}\)

然后考虑 \(m>0\) 的情况。

不难发现,对于每一条限制,相当于在二叉树的当前层,有一些区间被看成了是一个点。

因此,我们往限制中加入 \([1,n]\)\([i,i]\),答案为 \(\prod_{i=1}^{m} H(deg_i-1)\)

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int mod=998244353;
int t,n,m,ans,flag,vis[400005],cnt[400005];
struct node{
	int l,r;
}h[400005];
bool cmp(node a,node b){
	if(a.l!=b.l) return a.l<b.l;
	else return a.r>b.r;
}
int binpow(int a,int b){
	if(!b) return 1;
	int res=binpow(a,b/2);
	if(b&1) return res*res%mod*a%mod;
	else return res*res%mod;
}
int fac[400005];
int C(int n,int m){
	return fac[n]*binpow(fac[m],mod-2)%mod*binpow(fac[n-m],mod-2)%mod;
}
int H(int n){
	if(n<=0) return 1;
	return C(2*n,n)*binpow(n+1,mod-2)%mod;
}
stack<int> s;
signed main(){
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	cin>>t;
	while(t--){
		cin>>n>>m;
		fac[0]=ans=1;
		for(int i=1;i<=n*2;i++){
			fac[i]=fac[i-1]*i%mod;
		}
		for(int i=1;i<=m;i++){
			cin>>h[i].l>>h[i].r;
			if(h[i].l==h[i].r) vis[h[i].l]=1;
			if(h[i].l==1 && h[i].r==n) flag=1;
		}
		if(!flag) h[++m]=(node){1,n};
		flag=0;
		for(int i=1;i<=n;i++){
			if(!vis[i]) h[++m]=(node){i,i};
			vis[i]=0;
		}
		if(n==1){
			cout<<1<<'\n';
			continue;
		}
		sort(h+1,h+1+m,cmp);
		for(int i=1;i<=m;i++){
			while(s.size() && h[s.top()].r<h[i].l) s.pop();
			if(s.size()) cnt[s.top()]++,cnt[i]++;
			s.push(i);
		}
		cnt[1]++;
		for(int i=1;i<=m;i++){
			ans=ans*H(cnt[i]-2)%mod;
		}
		cout<<ans<<'\n';
		for(int i=1;i<=m;i++){
			cnt[i]=0;
		}
		while(s.size()) s.pop();
	}
	return 0;
}
posted @ 2025-02-17 21:28  _Kenma  阅读(8)  评论(0)    收藏  举报