zoukankan      html  css  js  c++  java
  • Educational Codeforces Round 69 (Rated for Div. 2) E. Culture Code dp(线段树转移) or 最短路计数

    题目链接

    题意: 

    有n个俄罗斯套娃  每个套娃有内积in 外积out  空间浪费指的是 多个(或者一个)套娃组合在一起  最大的套娃内部的空气的体积

    问有多少种套娃的组合方式(不能再被其他套娃套住  显然套住别人不会是最小答案 ) 使得空间浪费最小

    题解: 

    线段树优化dp

    • 设置dp[i].minn表示第i个套娃作为最内部套娃的所有套娃组合 的最小空间浪费 所以显然该状态从 $inj>outi$ 中转移过来
    • 先将n个套娃按照内积排序一遍 方便找到嵌套对象也就是j 
    • 首先显然要倒着dp  二分查找最小的j满足 $inj>out$ 所以 j-n 的套娃均满足转移条件  直接搜索最小值 然后在第i个位置插入 $dp[j].minn-(out[i]-in[i]) ,dp[j].num  $ 即可
    • 该树状数组用结构体方便很多  而且可以优化push_up 为merge (经过队友提醒 tql !!! )
    #include<bits/stdc++.h>
    using namespace std;
    const int N=2e5+10;
    int a[N],num,minn;
    #define  ll long long
    ll ans;
    const ll mod=1e9+7;
    struct node{ll minn,num;}t[N<<2];
    
    node merge(node a,node b)
    {
        if(a.minn==b.minn)return (node){a.minn,(a.num+b.num)%mod };
        if(a.minn<b.minn) return (node){a.minn,a.num};
        if(a.minn>b.minn) return (node){b.minn,b.num};
    }
    void upnode(int x,int v,int num,int l,int r,int pos)
    {
        if(l==r){t[pos]=(node){v,num};return;}
        int m=(l+r)>>1;
        if(x<=m)upnode(x,v,num,l,m,pos<<1);
        else upnode(x,v,num,m+1,r,pos<<1|1);
        t[pos]=merge(t[pos<<1],t[pos<<1|1]);
    }
    node qmin(int L,int R,int l,int r,int pos)
    {
        if(L<=l&&r<=R)return t[pos];
        int m=l+r>>1;node ans=(node){1000000000,0};
        if(L<=m)ans=merge(ans,qmin(L,R,l,m,pos<<1));
        if(R>m)ans=merge(ans,qmin(L,R,m+1,r,pos<<1|1));
        return ans;
    }
    struct NODE{int in,out;}s[N];
    int n;
    int main()
    {
        cin>>n;
        for(int i=1;i<=n;i++)scanf("%d%d",&s[i].out,&s[i].in);
        sort(s+1,s+1+n,[](NODE a,NODE b){return a.in<b.in;});
    
        for(int i=n;i>=1;i--)
        {
            int L=1,R=n,ans=-1;
            while(L<=R)
            {
                int mid=(L+R)>>1;
                if(s[mid].in>=s[i].out)ans=mid,R=mid-1;
                else L=mid+1;
            }
            if(ans==-1)upnode(i,s[i].in,1,1,n,1);
            else 
            {
                node u=qmin(ans,n,1,n,1);
                upnode(i,u.minn-(s[i].out-s[i].in),u.num,1,n,1);
            }
        }
        cout<<t[1].num;
        return 0;
    }
    code

    最短路计数

    • 我们要维护的东西是 $in[pk]  + (in[pk-1]-out[pk-1]) + ( in[pk-2] - out[pk-1] ) + ....+(in[pk1]-out[pk1])$ 的最小值及其个数  且满足 $out[pk] > in[n]$
    • 我们可以连图 从$0-n-1  add(i,i+1,in[i+1]-in[i])$  根据这条路径跑的话维护的就是 in[pk]  
    • 有 (in[pk-1] - out[pk-1] ) 可以来优化最短路    设置temp为最小的可以转移的对象 $add(i,temp,in[temp]-out[i])$ 可以发现恰好跑出来的就是上面那条式子
    #include<bits/stdc++.h>
    using namespace std;
    const int N=2e5+10;
    const int mod=1e9+7;
    struct node{int in,out;}s[N];
    int n,ans,dis[N],cnt[N],vis[N],pos,head[N],minn=1e9;
    struct Edge{int to,nex,v;}edge[N<<1];
    void add(int a,int b,int c){edge[++pos]=(Edge){b,head[a],c};head[a]=pos;};
    
    int main()
    {   
        cin>>n;
        for(int i=1;i<=n;i++)scanf("%d%d",&s[i].out,&s[i].in);
        sort(s+1,s+1+n,[](node a,node b){return a.in<b.in;});
        for(int i=0;i<n;i++)add(i,i+1,s[i+1].in-s[i].in);
        for(int i=1;i<=n;i++)
        {
            int temp=-1,L=1,R=n;
            while(L<=R)
            {
                int mid=L+R>>1;
                if(s[mid].in>=s[i].out)temp=mid,R=mid-1;else L=mid+1;
            }
            if(temp==-1)continue;
            else add(i,temp,s[temp].in-s[i].out);
        }
        memset(dis,0x3f,sizeof dis);
        dis[0]=0;cnt[0]=1;
        for(int i=0;i<=n;i++)
        {
            for(int j=head[i];j;j=edge[j].nex)
            {
                int v=edge[j].to;
                if(dis[i]+edge[j].v<dis[v])dis[v]=dis[i]+edge[j].v,cnt[v]=cnt[i];
                else if(dis[i]+edge[j].v==dis[v])cnt[v]+=cnt[i],cnt[v]%=mod;
            }
        }
        for(int i=1;i<=n;i++{if(s[i].out>s[n].in&&dis[i]<minn)minn=dis[i];}
        for(int i=1;i<=n;i++)
        if(s[i].out>s[n].in&&dis[i]==minn)ans=(ans+cnt[i])%mod;
        cout<<ans;
        return 0;
    }
    Code
  • 相关阅读:
    Python3.x和Python2.x的区别
    python 列表 元组 字典
    Wireshark TCP报文到达确认(ACK)机制
    Wireshark Tcp三次握手
    Python Vim配置 Win7x64
    Workstation guest fails to restart or resume
    python 枚举目录下所有子目录和文件,输出列表
    Python按行读文件 高级
    python 注释
    十一、设备初始化(ADK4.0)
  • 原文地址:https://www.cnblogs.com/bxd123/p/11695048.html
Copyright © 2011-2022 走看看