zoukankan      html  css  js  c++  java
  • CSP-S 模拟76

      最简单的T1没去做,T2,T3倒是A了

      

       序列

      将序列分成B块,每块长度最大为A,每一个块都是连续的上升序列,且前一个块所有权值大于后边所有块的所有权值

      也就是类似与(8,9,10)(5,6,7)(2,3,4))(1)的样子,显然最长上升子序列不超过A,所有块中取出一个值组成最长下降子序列B

    #include<iostream>
    #include<cstdio>
    using namespace std;
    int T,n,A,B,a[110000];
    int main(){
        scanf("%d",&T);
        while(T--){
            scanf("%d%d%d",&n,&A,&B);
            if(n-A<B-1||A*B<n){
                puts("No");
                continue;
            }
            for(register int i=1,j=n-A+1;i<=A;i++,j++)    a[i]=j;
            if(B>1){
                int las=n-A+1;
                int bg=A;
                for(register int i=B-1;i>=1;i--){
                    int w=min(las-i,A);
                    bg+=w;
                    for(register int j=1,k=bg;j<=w;j++,k--){
                        a[k]=--las;
                    }
                }
            }
            puts("Yes");
            for(register int i=1;i<=n;i++) printf("%d ",a[i]);
            puts("");
        }
    }
    View Code

      购物

      显然$kin[(sum+1)/2,sum] $,可以做一个背包(大神说的,我不知道什么叫背包QWQ),维护k的取值区间,加上一个a[i],就是将所有区间基础上加上[(a[i]+1)/2,a[i]](保留原来区间,加入新的区间),会发现会有一堆连起来的区间

      显然是个板子——Old Driver tree (老司机树)——又称柯朵莉树

    #include<iostream>
    #include<cstdio>
    #include<set>
    #include<algorithm>
    #include<vector>
    using namespace std;
    struct node{
        long long l,r;
        bool operator < (const node x)const{
            return (l<x.l)||(l==x.l&&r<x.r);
        }
    };
    set<node>s;
    vector<node>v;
    int n,a[110000];
    void add(int x){
        auto it=s.begin();
        for(;it!=s.end();it++){
            node w=*it;
            v.push_back((node){w.l+(x+1)/2,w.r+x});
        }
        while(v.size()){
            s.insert(v.back());
            v.pop_back();
        }
    }
    void split(){
        auto it=s.begin();
        for(;it!=s.end();){
            auto L=it;
            it++;
            if(it==s.end()) break;
            if((*L).r>=(*it).l){
                node w=(node){(*L).l,(*it).r};
                s.erase(it);
                s.erase(L);
                s.insert(w);
                it=s.lower_bound(w);
            }
        }
    }
    int main(){
        //freopen("2.in","r",stdin);
        //freopen("2.out","w",stdout);
        scanf("%d",&n);
        for(register int i=1;i<=n;i++) scanf("%d",&a[i]);
        s.insert((node){0,0});
        for(register int i=1;i<=n;i++){
            add(a[i]);
            split();
        }
        long long ans=0;
        auto it=s.begin();
        for(;it!=s.end();it++){
            if((*it).l==0&&(*it).r==0) continue;
            ans+=((*it).r-(*it).l+1);
        }
        printf("%lld
    ",ans);
    }
    View Code

      计数

      首先要知道: 前序遍历——根,左,右

               中序遍历——左,根,右

               后序遍历——左,右,根

      对于$M=0$即无限制的情况,我们只需要考虑前序遍历,对于一个前序遍历$[l,r]$,第一个位置$l$一定是根,从第二个位置开始到某一个位置是左子树,从该位置后一个位置到最后是右子树,可以枚举$iin[l,r]$,$[l+1,i]$为左子树,$[i+1,r]$为右子树,那么方案数是$sumlimits_{i=l}^{r}f[l+1][i]*f[i+1][r]$,包含无左子树和无右子树的情况

      那么就可以不断划分子问题,知道l==r或l>r,返回1即可

      但是这样会T成狗,可以发现对于任意长度为len的序列,在没有限制的情况下方案数是固定的,所以用数组f[len]记录长度为len的区间的方案数,记忆化搜索一下会快到飞起

      考虑加上限制,限制有两种: 在中序遍历中 $1.$$u$先于$v$出现 $2.$$u$晚于$v$出现

      因为先序遍历是从$1$到$n$,$u$,$v$之间有谁大谁小的不同情况

      我们让它一边倒,只考虑$v<u$的情况,因为先序遍历是从小的为根再考虑到大的,所以$v>u$的情况会在$u$的位置考虑到

      对于$v<u$的情况,在先序遍历所能构造的二叉树中,$u$要么在$v$的某一个祖宗的右子树中,要么在v的子树中——左子树或右子树

    • 对于中序遍历,$u$先于$v$出现,考虑上面的情况,$u$必定在$v$的左子树中,那么在划分$[v,r]$的序列时,$[v+1,u]$的区间只能是左子树,即枚举$v$的左右子树的分界线至少要在$u$及其以后才行
    • 对于中序遍历,$u$晚于$v$出现,同样考虑上面的情况,$u$只能在$v$的祖宗的右子树,或v的右子树中。
      • 对于第一种在祖宗的右子树中,在考虑祖宗的子树的时候,$v$,$u$不会被划分到一个序列里,因此在$v$为根的时候不需要考虑;
      • 对于第二种在$v$的右子树中,和$u$先与$v$出现类似,$u$必须是右子树,所以$[u,r]$只能是右子树,即枚举$v$的左右子树的分界线最大也要小于$u$

      综上所述,我们可以预处理出$L[x]$,$R[x]$,分别表示以$x$做根,枚举左右子树边界i的范围,然后dfs搜索即可,而对于记忆化,因为现在对于长度相等的序列在有限制的条件下方案不一样,但是对于一个区间$[l,r]$的方案数是肯定不变的,所以记忆化$f[l][r]$即可

      $L[x]$,为大于x的里边最后一个在中序遍历中先于$x$出现的点

      $R[x]$,为大于$x$的里边第一个在中序遍历中晚于$x$出现的点的前一个位置

      注意如果$R[x]$大于当前以$x$打头的序列$[l,r]$的$r$,那么说明$R[x]$那些晚于$x$出现的点在$x$的祖宗的右子树中,所以枚举分界线的右边界为$min(R[x],r)$

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    using namespace std;
    int T,n,m,a[410][410],L[410],R[410];
    const long long mod=1e9+7;
    long long f[410],dp[410][410];
    long long dfs(int l,int r){
        if(l>r) return f[0]=1;
        if(l==r) return f[1]=1;
        if(f[r-l+1]) return f[r-l+1];
        long long ans=0;
        for(register int i=l;i<=r;i++){
            f[r-l+1]=(f[r-l+1]+dfs(l+1,i)*dfs(i+1,r)%mod)%mod;
        }
        f[r-l+1]%=mod;
        return f[r-l+1];
    }
    long long DFS(int l,int r){
        if(l>r) return 1;
        if(L[l]>r) return 0;
        if(l==r) return 1;
        if(dp[l][r]!=-1) return dp[l][r];
        dp[l][r]=0;
        for(register int i=L[l];i<=min(R[l],r);i++){
            dp[l][r]=(dp[l][r]+DFS(l+1,i)*DFS(i+1,r)%mod)%mod;
        }
        return dp[l][r];
    }
    int main(){
        scanf("%d",&T);
        while(T--){
            scanf("%d%d",&n,&m);
            if(m==0) printf("%lld
    ",dfs(1,n));
            else{
                memset(a,0,sizeof(a));
                memset(dp,-1,sizeof(dp));
                for(register int i=1,x,y;i<=m;i++) scanf("%d%d",&x,&y),a[x][y]=1;
                for(register int i=1;i<=n;i++){
                    L[i]=i,R[i]=i;
                    for(register int j=i+1;j<=n;j++){
                        if(a[j][i])    L[i]=j;
                    }
                    for(register int j=i+1;j<=n;j++){
                        if(a[i][j])    break;
                        R[i]=j;
                    }
                }
                printf("%lld
    ",max(DFS(1,n),0ll));
            }
        }
    }
    View Code

      

  • 相关阅读:
    Jenkins构建、推送、拉取镜像和发布应用
    我们是如何做DevOps的?
    记录这两年是如何一步一步转型到.net core+k8s
    spring cloud+.net core搭建微服务架构:服务注册(一)
    .net core gRPC与IdentityServer4集成认证授权
    同时支持EF+Dapper的混合仓储,助你快速搭建数据访问层
    如何更优雅的在kubernetes平台下记录日志
    spring cloud+.net core搭建微服务架构:Api授权认证(六)
    spring cloud+.net core搭建微服务架构:配置中心续(五)
    spring cloud+.net core搭建微服务架构:配置中心(四)
  • 原文地址:https://www.cnblogs.com/heoitys/p/11689915.html
Copyright © 2011-2022 走看看