人,只有自己站起来,这个世界才能属于他。|

园龄:粉丝:关注:

CF Round 997 题解合集

here.

C

考虑这样一种构造:

1,2,3,,n1,n,1,2,3,,n1,n

或者是:

1,2,3,,n2,n1,n,1,2,3,,n2,n1

这里的 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

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

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

注意到,对于每个不合法区间,都存在唯一一个 x,使得令 aix,ai=1;ai>x,ai=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 的最大值是 2n1,具体构造可以考虑建立一棵二叉广义线段树。

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

首先考虑 m=0 的情况。

fi 表示 n=i 时的答案,初始 f1=1,不难得到转移:

fi=j=1n1fjfij

然后这个形式看起来很像卡特兰数,打表发现 fi=Hi1

然后考虑 m>0 的情况。

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

因此,我们往限制中加入 [1,n][i,i],答案为 i=1mH(degi1)

#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;
}

本文作者:Kenma

本文链接:https://www.cnblogs.com/Kenma/p/18720875

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   _Kenma  阅读(4)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起