zoukankan      html  css  js  c++  java
  • 洛谷P4229 [清华集训2017] 某位歌姬的故事

    不难发现题目中的每个限制可以进行转化:

    [large max_{i=l}^r{ h_i}=m Leftrightarrow forall i in [l,r],h_i leqslant m and exist i in[l,r],h_i=m ]

    求出每个位置的上界,得 (exist i in[l,r],h_i=m) 只可能是上界等于 (m) 的位置贡献的,那么考虑对每种上界分别来 (DP) 方案数,只要满足每段限制区间至少有一个位置达到上界即可。

    (f_{i,j}) 为在考虑某一上界的限制下,考虑了上界为该上界的前 (i) 个数,最后一个达到上界的数在 (j) 位置的方案数,得:

    [largeegin{aligned} f_{i,j}&=(m-1)^{len_i}f_{i-1,j} (lim_ileqslant j<i) \ f_{i,i}&=(m^{len_i}-(m-1)^{len_i})sum_{j=0}^{j<i}f_{i-1,j} end{aligned} ]

    其中 (len_i) 为位置 (i) 到位置 (i+1) 的区间长度,(lim_i) 为位置 (i) 对应的达到上界的位置最小值。

    为方便处理,离散化时采用左闭右开。

    复杂度为 (O(TQ^2))

    #include<bits/stdc++.h>
    #define maxn 2010
    #define p 998244353
    using namespace std;
    typedef long long ll;
    template<typename T> inline void read(T &x)
    {
        x=0;char c=getchar();bool flag=false;
        while(!isdigit(c)){if(c=='-')flag=true;c=getchar();}
        while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
        if(flag)x=-x;
    }
    ll T,n,q,a,ans=1,tot1,tot2;
    ll s1[maxn],s2[maxn],mx[maxn],lim[maxn],d[maxn],f[maxn][maxn];
    struct node
    {
        ll l,r,m;
    }t[maxn];
    ll qp(ll x,ll y)
    {
        ll v=1;
        while(y)
        {
            if(y&1) v=v*x%p;
            x=x*x%p,y>>=1;
        }
        return v;
    }
    ll calc(ll x)
    {
        int cnt=0;
        for(int i=1;i<=tot1;++i)
            if(mx[i]==x)
                d[++cnt]=i;
        if(!cnt) return 0;
        for(int i=1;i<=cnt;++i) lim[i]=0;
        for(int i=1;i<=q;++i)
        {
            if(t[i].m!=x) continue;
            ll l,r;
            l=lower_bound(d+1,d+cnt+1,t[i].l)-d;
            r=lower_bound(d+1,d+cnt+1,t[i].r)-d-1;
            lim[r]=max(lim[r],l);
        }
        f[0][0]=1;
        for(int i=1;i<=cnt;++i)
        {
            ll v1=qp(x,s1[d[i]+1]-s1[d[i]]),v2=qp(x-1,s1[d[i]+1]-s1[d[i]]);
            f[i][i]=0;
            for(int j=0;j<i;++j)
            {
                if(j>=lim[i]) f[i][j]=f[i-1][j]*v2%p;
                else f[i][j]=0;
                f[i][i]=(f[i][i]+f[i-1][j]*(v1-v2+p)%p)%p;
            }
        }
        ll v=0;
        for(int i=1;i<=cnt;++i) v=(v+f[cnt][i])%p;
        return v;
    }
    void solve()
    {
        read(n),read(q),read(a),ans=1,tot1=tot2=0;
        for(int i=1;i<=q;++i)
        {
            read(t[i].l),read(t[i].r),read(t[i].m),t[i].r++;
            s1[++tot1]=t[i].l,s1[++tot1]=t[i].r,s2[++tot2]=t[i].m;
        }
        s1[++tot1]=1,s1[++tot1]=n+1;
        sort(s1+1,s1+tot1+1),tot1=unique(s1+1,s1+tot1+1)-s1-1;
        sort(s2+1,s2+tot2+1),tot2=unique(s2+1,s2+tot2+1)-s2-1;
        for(int i=1;i<=tot1;++i) mx[i]=a+1;
        for(int i=1;i<=q;++i)
        {
            t[i].l=lower_bound(s1+1,s1+tot1+1,t[i].l)-s1;
            t[i].r=lower_bound(s1+1,s1+tot1+1,t[i].r)-s1;
            for(int j=t[i].l;j<t[i].r;++j) mx[j]=min(mx[j],t[i].m);
        }
        for(int i=1;i<=tot2;++i) ans=ans*calc(s2[i])%p;
        for(int i=1;i<tot1;++i)
            if(mx[i]==a+1)
                ans=ans*qp(a,s1[i+1]-s1[i])%p;
        printf("%lld
    ",ans);
    }
    int main()
    {
        read(T);
        while(T--) solve();
        return 0;
    }
    
  • 相关阅读:
    在浏览器中浏览git上项目目录结构
    部署elasticsearch(三节点)集群+filebeat+kibana
    谷歌浏览器安装Elasticsearch-head 插件
    Logstash配置文件修改自动加载和指定目录进行启动
    使用Dbvisualizer 连接 Elasticsearch
    Elasticsearch常见用法-分布式集群
    Elasticsearch常见用法-入门
    Elastic Stack 7.5.0白金版永不过期
    配置 Nginx 反向代理 WebSocket
    ES7.3.0配置
  • 原文地址:https://www.cnblogs.com/lhm-/p/13779430.html
Copyright © 2011-2022 走看看