CF Round 997 题解合集
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;
}