• Codeforces Round #622 (Div. 2)


    Codeforces Round #622 (Div. 2)

    题目链接:https://codeforces.com/contest/1313

    A. Fast Food Restaurant

    算贪心吧,先一个一个选,再两个两个选,最后三个三个选,选两个的时候注意挑选最多的两个。

    B. Different Rules

    推公式吧,感觉就和田忌赛马差不多,但是我wa了几次,就是当两次排名都是倒数第一时,我会算出负数。

    代码: 一时兴起用了java

        import java.util.*;
        import java.math.*;
        import java.io.*;
        public class a1{
            public static void main(String[] args){
                Scanner cin=new Scanner(System.in);
                Long q=cin.nextLong();
                for(int i=1;i<=q;i++){
                    Long n,a,b,ans1,ans2;
                    n=cin.nextLong();
                    a=cin.nextLong();
                    b=cin.nextLong();
                    ans1=n-Math.max(0,Math.min(n*2-b-a-1,n-1));
                    
                    ans2=Math.min(a+b-1,n);
                    System.out.println(ans1+" "+ans2);
                }
            }
        }
    

    C1 C2 Skyscrapers

    题解

    C1可以直接枚举极大值点然后再扫一遍数组,(O(n^2)).

    C2就是在枚举最大值时优化求值过程。

    我们创建一个数组(f[i])表示(1..i变成单增序列后的权值和)。那么从(f[i-1]到f[i])肯定是有联系的。我们只要找到左边第一个比(i位置权值小的位置,将他记作x),则:

    • (f[i]=f[x]+(i-x)*a[i],(a[i]是i点的权值))

    那么问题就变成了怎么求左边第一个比(a[i]小的数的位置),这个可以用单调队列。当然也可以用一种神奇的方法,那就是先判断(a[i]和a[i-1]的大小关系):

    • (a[i-1]le a[i]) : (L[i]=i-1); ((L[i]为i左边第一个大于等于a[i]的数的位置))

    • (a[i]>a[i-1]) : (那么再判断a[L[i-1]]和a[i]的关系)

    这样貌似时间复杂度得不到保证,但是实际上速度很快,应该是(O(n))。我们可以分析一下什么时候回往前跳。就是当(a[i-1]>a[i]),但是之后就再也不会跳到(a[i-1])了,因为(L[i]<i-1),也就是每个点跳一次就不会再继续碰到它了。所以当最多跳(n)次。

    当然感觉这种方法比较非主流,好好的单调队列不用,用这种奇葩算法。

    代码一 非主流算法 (O(n))

    import java.util.*;
    import java.math.*;
    import java.io.*;
    public class a1{
        static class G{
            final static int N=1000050;
            int n;
            int[] a=new int[N];
            int[] l=new int[N];
            Long[] f=new Long[N];
            public int findL(int i,int p){
                if (a[i]<p)return i;
                else return findL(l[i],p);
            }
            public Long findVal(int i, int p){
                if (a[i]<p) return f[i];
                else return findVal(l[i],p)+(long)(i-l[i])*p;
            }
            public void work(){
                a[0]=0;
                l[1]=0;
                f[0]=0L;
                for(int i=1;i<=n;i++)
                    l[i]=findL(i-1,a[i]);
                for(int i=1;i<=n;i++)
                    f[i]=findVal(i-1,a[i])+Long.valueOf(a[i]);
            }
            public void handle(int k){
                for(int i=k-1;i>=1;i--)
                    a[i]=Math.min(a[i],a[i+1]);
                for(int i=k+1;i<=n;i++)
                    a[i]=Math.min(a[i],a[i-1]);
            }
        }
        public static void main(String[] args){
            
            Scanner cin=new Scanner(System.in);
            G arr1=new G();
            G arr2=new G();
            int n;
            n=arr2.n=arr1.n=cin.nextInt();
            for(int i=1;i<=n;i++)
                arr1.a[i]=cin.nextInt();
            arr1.work();
            for(int i=1;i<=n;i++)
                arr2.a[i]=arr1.a[n+1-i];
            arr2.work();
            Long ans=0L;
            int tp=0;
            for(int i=1;i<=n;i++){
                if (arr1.f[i]+arr2.f[n-i+1]-Long.valueOf(arr1.a[i])>ans){
                    ans=arr1.f[i]+arr2.f[n-i+1]-Long.valueOf(arr1.a[i]);
                    tp=i;
                }
            }
            arr1.handle(tp);
            for(int i=1;i<=n;i++)
                System.out.print(arr1.a[i]+" ");
        }
    }
    

    代码二 单调队列 (O(n))

        #include<bits/stdc++.h>
        using namespace std;
        typedef long long ll;
        using vl=vector<ll>;
        using pll=pair<ll,ll>;
         
        int n;
         
        void solve(vl &a, vl &ans){
            deque<pll>Q;
            for(int i=1;i<=n;i++){
                while(!Q.empty() && a[i]<=Q.back().second)Q.pop_back();
                int pre=Q.empty()?0:Q.back().first;
                ans[i]=ans[pre]+a[i]*(i-pre);
                Q.push_back({i,a[i]});
            }
        }
        void print(vl &a,ll k, vl &ans){
            ans[k]=a[k];
            for(int i=k-1;i>=1;i--){
                ans[i]=min(a[i],ans[i+1]);
            }
        }
        int main(){
            #ifndef ONLINE_JUDGE
            freopen("aa.in","r",stdin);
            #endif
            ios::sync_with_stdio(false);
            cin.tie(0);
            cin>>n;
            vl init(n+5,0);
            vl a,a_rev,ansl,ansr;
            pll max={0,0};
            a=a_rev=ansl=ansr=init;
            for(int i=1;i<=n;i++) cin>>a[i],a_rev[n+1-i]=a[i];
            solve(a,ansl);
            solve(a_rev,ansr);
            for(int i=1;i<=n;i++)
                if (ansl[i]+ansr[n+1-i]-a[i]>max.second){
                    max={i,ansl[i]+ansr[n+1-i]-a[i]};
                }
            print(a,max.first,ansl);
            print(a_rev,n-max.first+1,ansr);
            for(int i=1;i<=max.first;i++)cout<<ansl[i]<<" ";
            for(int i=n-max.first;i>=1;i--)cout<<ansr[i]<<" 
    "[i==1];
        }
    

    D. Happy New Year

    题解:

    (kle8),虽然我也知道可以对于每个点暴力枚举覆盖情况,也就(2^k)种状态。
    但是枚举完之后我不知到怎么由前面的状态转移,主要是有很多区间交在一起,我不会处理。上网看了题解,发现一个神奇的东西,扫描线。也就是把所有的端点变成两个独立点,再标记它是左端点还是右端点。具体步骤:

    1. 先将端点数组排序
    2. 再扫描这个数组,
    3. 碰到左端点,就给他分配一个编号(1..k中的一个),并进行处理
    4. 碰到右端点,就空出来原来的编号,并处理一下

    感觉这么说完,还是很抽象。我们可以建一个数组(dp[i][j])表示,第(i)个端点所表示的距离,状态为(0le j<2^k)的最大覆盖情况。这个(dp)讲起来有点麻烦,这里还是讲一下思路吧。因为如果前面和当前端点没有交集的区间我们只需要求一个最大值即可,而相交的部分,就可以通过设置状态来解决,这样就可以完成转移。具体可以看代码。

    代码:

        #include<bits/stdc++.h>
        using namespace std;
        using vi=vector<int>;
        using pii=pair<int,int>;
        using vpii=vector<pii>;
         
        const int INF=0x7f7f7f7f;
         
        bool cmp(pii a, pii b){return a.first==b.first?a.second>b.second:a.first<b.first;};
        int n,m,k;
        int main(){
            #ifndef ONLINE_JUDGE
            freopen("aa.in","r",stdin);
            #endif
            ios::sync_with_stdio(false);
            cin.tie(0);
            cin>>n>>m>>k;
            vpii p;
            vi bit,dp(1<<k,-INF),newdp,init(1<<k,0);
            vi num(n+50,0);
            set<int> S;
            bit=newdp=init;
            for(int i=0;i<k;i++)S.insert(i);
            for(int i=1;i<(1<<k);i++)bit[i]=bit[i>>1]^(i&1);
            for(int i=1;i<=n;i++){
                int l,r;
                cin>>l>>r;
                p.push_back({l,i});
                p.push_back({r,-i});
            }
            sort(p.begin(),p.end(),cmp);
            int pre=p[0].first-1; dp[0]=0;
            for(int i=0;i<p.size();i++){
                int x=p[i].first, id=p[i].second;
                for(int j=1;j<(1<<k);j++) dp[j]+=(x-pre)*bit[j];
                if (id>0){
                    num[id]=*S.begin(); S.erase(S.begin());
                    for(int j=0;j<(1<<k);j++){
                        if ((j>>num[id])&1) newdp[j]=dp[j^(1<<num[id])]+2*bit[j]-1;
                        else newdp[j]=dp[j];
                    }
                }else{
                    id=-id;
                    S.insert(num[id]);
                    int val=x-pre;
                    for(int j=0;j<(1<<k);j++){
                        if ((j>>num[id])&1){
                            newdp[j^(1<<num[id])]=max(dp[j^(1<<num[id])],dp[j]);
                            newdp[j]=-INF;
                        }else{
                            newdp[j]=dp[j];
                        }
                    }
                }
                pre=x;
                dp=newdp;
            }
            cout<<dp[0];
        }
    
  • 相关阅读:
    OTA在线升级Android7.1系统迅为IMX6Q开发板支持SATA,PCIE,EIM总线,WIFI蓝牙
    迅为iTOP2K1000开发板龙芯中科国产64位Loognix系统工业核心主板
    四核处理器IMX6Q开发板Android7.1系统支持SATA、PCIE、EIM总线、WIFI蓝牙OTA远程升级提供OpenWrt文件系统
    迅为瑞芯微RK3399开发板Debian9多媒体测试之Gstreamer测试
    迅为IMX6ULL开发板Qt for Android搭建开发环境
    迅为RK3568开发板Ubuntu系统编写运行Qt工程
    src/caffe/proto/caffe.pb.h:17:2: error: #error This file was generated by an older version of protoc which is #error This file was generated by an older version of protoc which is
    ubuntu/ linux挂载新硬盘
    so 对XXX未定义的引用
    nvcaffe 的一个问题解决
  • 原文地址:https://www.cnblogs.com/mmmqqdd/p/12398876.html
Copyright © 2020-2023  润新知