CF Round 1008 题解合集

here.

here.

2D

抖音小游戏。

考虑从后往前 DP,设 \(f_{i,0/1}\) 表示在第 \(i\) 个位置放一个人,会给结果贡献几个人。

转移枚举当前位置是否是乘法:

  • \(f_{i,j}=f_{i+1,j}\),当前位置是加法;

  • \(f_{i,j}=a_{i}\max(f_{i+1,0},f_{i+1,1})\),当前位置是乘法。

然后从前往后贪心,每次把人放到贡献大的位置上。

复杂度 \(O(n)\)

2E & 1B

考虑我们需要知道每个二进制位,是 \((0,0)\)\((0,1)\),还是 \((1,1)\)

又发现困扰我们的实际是加法的进位。

于是我们可以分别考虑奇数位和偶数位,询问奇数位时,把 \(n\) 的偶数位全变成 \(1\),询问偶数位时,把 \(n\) 的奇数位全变成 \(1\),在最后计算答案时减去 \(2n\)。这样就能避免进位对下一位带来的干扰。

2F & 1C

这个真的只有 2300 吗。

\(cnt_0\) 表示序列中 \(0\) 的个数,\(cnt_1\) 表示序列中 \(1\) 的个数,\(S=cnt_1-cnt_0\),那么贪心地考虑,最后分数一定是 \(\lfloor\frac{S}{2}\rfloor\lceil\frac{S}{2}\rceil\),也就是:

\[\frac{S^2-S\bmod2}{4} \]

所以我们要对所有的子序列 \(T\) 计算上面的式子之和,也就是:

\[\frac{1}{4}\sum_{T}S_T^2-S_T \bmod 2 \]

考虑后一项,实际上是 \(2^{n-1}\),因为 \(S_T\) 的变化是连续的,所以这一项的值只有在 \(|T| \bmod 2=1\) 时才是 \(1\)

现在的问题是前一项。我们还是希望合并处理系数,所以我们想要求的系数,实际上是:

\[\sum_{T} |T| \]

如果我们能求出这个式子,那么相当于把枚举子集求答案转化成了只对全集求答案。

\[\sum_{T}|T|=\sum_{i=1}^{n}i\binom{n}{i} \]

\[\sum_{T}|T|=\sum_{i=1}^{n}n\binom{n-1}{i-1} \]

\[\sum_{T}|T|=n2^{n-1} \]

所以说,对于集合内的一个为 \(1\) 的系数,实际上就是全集一个 \(2^{n-1}\) 的系数。意会即可。

\(a_i=0\) 时,\(val_i=-1\);当 \(a_i=1\) 时,\(val_i=1\)。这样我们的答案变成:

\[\frac{1}{4}(2^{n-2}((\sum_{i=1}^{n}val_i)^2+n)-2^{n-1}) \]

维护即可。

复杂度 \(O(n)\)

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int mod=998244353;
char ch;
int t,n,m,sum,pos,a[200005];
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;
}
signed main(){
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    cin>>t;
    while(t--){
        cin>>n>>m;
        sum=0;
        for(int i=1;i<=n;i++){
            cin>>ch;
            if(ch=='0') a[i]=-1;
            else a[i]=1;
            sum+=a[i];
        }
        for(int i=1;i<=m;i++){
            cin>>pos;
            sum-=a[pos];
            a[pos]*=-1;
            sum+=a[pos];
            cout<<(binpow(4,mod-2)*((sum*sum%mod+n)%mod*(n!=1?binpow(2,n-2):binpow(2,mod-2))%mod-binpow(2,n-1))%mod+mod)%mod<<'\n';
        }
    }
    return 0;
}

2G & 1F

转化题意后,相当于每次选择若干位置 \(p_i\),满足相邻两个位置奇偶性不同,然后将这些位置减去 \(1\)

\(b_i=\sum_{j=1}^ia_j[a_j \bmod 2=1]-\sum_{j=1}^ia_j[a_j \bmod 2=0]\),我们猜测答案为:

\[\sum_{l \le r} \max_{i=l-1}^{r} b_i-\min_{i=l-1}^{r} b_i \]

不难发现,这是答案的一个下界,但是这个下界好像能过样例的样子。

于是写一发扫描线,发现过了。

证明咕了。

复杂度 \(O(n \log n)\)

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int mod=998244353;
int t,n,ans,a[200005],b[200005],s1[200005],s2[200005],top1,top2;
int val[400005],ls[400005],rs[400005],tag[400005],dcnt,rt;
void pushup(int x){
    val[x]=(val[ls[x]]+val[rs[x]])%mod;
}
void pushdown(int l,int r,int x){
    if(!tag[x]) return;
    int mid=(l+r)>>1;
    val[ls[x]]=(val[ls[x]]+(mid-l+1)*tag[x]%mod)%mod;
    val[rs[x]]=(val[rs[x]]+(r-mid)*tag[x]%mod)%mod;
    tag[ls[x]]=(tag[ls[x]]+tag[x])%mod;
    tag[rs[x]]=(tag[rs[x]]+tag[x])%mod;
    tag[x]=0;
}
void build(int l,int r,int &x){
    x=++dcnt;
    val[x]=tag[x]=0;
    if(l==r) return;
    int mid=(l+r)>>1;
    build(l,mid,ls[x]);
    build(mid+1,r,rs[x]);
    pushup(x);
}
void modify(int l,int r,int ql,int qr,int k,int x){
    if(ql<=l && r<=qr){
        val[x]=(val[x]+(r-l+1)*k%mod)%mod;
        tag[x]=(tag[x]+k)%mod;
        return;
    }
    pushdown(l,r,x);
    int mid=(l+r)>>1;
    if(ql<=mid) modify(l,mid,ql,qr,k,ls[x]);
    if(qr>=mid+1) modify(mid+1,r,ql,qr,k,rs[x]);
    pushup(x);
}
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];
            b[i]=b[i-1];
            if(i&1) b[i]=b[i]+a[i];
            else b[i]=b[i]-a[i];
        }
        memcpy(a,b,sizeof(a));
        top1=top2=0;
        s1[0]=s2[0]=-1;
        build(0,n,rt);
        for(int i=0;i<=n;i++){
            while(top1 && a[s1[top1]]>a[i]){
                modify(0,n,s1[top1-1]+1,s1[top1],a[s1[top1]]-a[i],rt);
                top1--;
            }
            while(top2 && a[s2[top2]]<a[i]){
                modify(0,n,s2[top2-1]+1,s2[top2],a[i]-a[s2[top2]],rt);
                top2--;
            }
            s1[++top1]=i;
            s2[++top2]=i;
            ans=((ans+val[1])%mod+mod)%mod;
        }
        cout<<ans<<'\n';
        ans=dcnt=rt=0;
    }
    return 0;
}
posted @ 2025-04-12 18:01  _Kenma  阅读(8)  评论(0)    收藏  举报