zoukankan      html  css  js  c++  java
  • 2020沈阳区域赛补题&总结

    7月18号的比赛,一直拖着没补。想想就这样放着不太行,还是开个坑慢慢填吧

    考前一个月备战期末没摸acm,最后rank85/265,罚时卡出ag线,大概就是报应吧。

    D. Journey to Un'Goro

    传送门

    构造。

    很关键的一个想法:令(p_i)表示从(1)(i)位置中(r)数量的奇偶性,(i)(j)(r)的数量为奇数的条件便是(p_{i-1},p_j)不同。(特别地,(p_0)为偶)

    那么对于(n)的一种构造方式,考虑有(x)个奇数点,(n+1-x)个偶数点,那么题中要求的((i,j))对数就是(x*(n-x+1))。均值不等式,想要最大化合法对数就是使得奇偶点数为(lceilfrac{n+1}{2} ceil)(lfloorfrac{n+1}{2} floor)(谁大谁小都行),然后就排列就是了。由于从第(0)位开始且该位确定是偶,所以排列确定,你的(br)序列也就定了。排列中当前位与前一位不同,这一位就是(r),反之是(b)

    那么dfs就行了,贪心从前往后做一位一位的做,在满足奇偶点的数量约束的前提下((lceilfrac{n+1}{2} ceil)),优先保证当前位与前一位奇偶相同(也就是填(b)),搜到了100个答案就直接终止。

    #include<bits/stdc++.h>
    using namespace std;
    int n,tot=0;
    int ans[100005],num[2];
    void dfs(int len)
    {
        if(tot>=100)
            return;
        if(len>n)
        {
            for(int i=1;i<=n;i++)
            {
                if(ans[i]==ans[i-1])
                    printf("b");
                else
                    printf("r");
            }
            tot++;
            if(tot>=100)
                exit(0);
            printf("
    ");
            return;
        }
        int p=ans[len-1];
        if(num[p]<n/2+1)
        {
            num[p]++;
            ans[len]=p;
            dfs(len+1);
            num[p]--;
        }
        p=p^1;
        if(num[p]<n/2+1)
        {
            num[p]++;
            ans[len]=p;
            dfs(len+1);
            num[p]--;
        }
    }
    int main()
    {
        scanf("%d",&n);
        long long p=n;
        ans[0]=0;
        num[0]=1;
        num[1]=0;
        printf("%lld
    ",(p+1ll)/2ll*(p/2ll+1ll));
        dfs(1);
        return 0;
    }
    

    H. The Boomsday Project

    传送门
    先考虑怎么暴力

    显然你一定是把一张优惠卡用到不能用了(时间限制或次数限制)

    将每次租车按时间排序,(dp[i])表示恰好处理完前(i)次租车的最小花费,(f[i][j])表示在第(i)次用第(j)张卡,能覆盖到的最后租车是那次,(f)数组可以二分查找来得出

    转移:

    [dp[i+f[i+1][j]]=max(dp[i]+c,dp[i+f[i+1][j]]) ]

    [dp[i+1]=max(dp[i+1],dp[i]+r) ]

    再考虑怎么优化掉这个(log)

    注意到(f)数组具有单调性:

    [f[i+1][j]>=f[i][j] ]

    事实上我们每次算(f[i][j])时,只需要从(f[i-1][j])开始递推,一个一个地往后挪即可

    特别地,为了防止MLE,f数组需要使用滚动数组

    #include<bits/stdc++.h>
    using namespace std;
    int n,m,r,p,q,cnt=0;
    int d[505],k[505],c[505],rt[300005],f[2][505];
    long long dp[300005];
    int main()
    {
        memset(f,0,sizeof(f));
        scanf("%d%d%d",&n,&m,&r);
        for(int i=1;i<=n;i++)
            scanf("%d%d%d",&d[i],&k[i],&c[i]);
        for(int i=1;i<=m;i++)
        {
            scanf("%d%d",&p,&q);
            for(int j=cnt+1;j<=cnt+q;j++)
            {
                rt[j]=p;
                dp[j]=1e18;
            }
            cnt+=q;
        }
        sort(rt+1,rt+1+cnt);
        dp[0]=0;
        rt[0]=0;
        for(int i=0;i<=cnt-1;i++)
        {
            dp[i+1]=min(dp[i+1],dp[i]+1ll*r);
            for(int j=1;j<=n;j++)
            {
                for(int l=f[0][j];l<=cnt;l++)
                {
                    if(l-i<=k[j]&&rt[l]-rt[i+1]<=d[j]-1)
                        f[1][j]=l;
                    else
                        break;
                }
                f[0][j]=f[1][j];
                dp[f[0][j]]=min(dp[i]+1ll*c[j],dp[f[0][j]]);
                //printf("%d %d %d %lld %lld
    ",i,j,f[0][j],dp[i],dp[i+f[0][j]]);
            }
        }
        printf("%lld",dp[cnt]);
        return 0;
    }
    小鳥の翼がついに大きくなって , 旅立ちの日だよ , 遠くへと広がる海の色暖かく , 夢の中で描いた絵のようなんだ , 切なくて時をまきもどしてみるかい ? No no no いまが最高! だってだって、いまが最高!
  • 相关阅读:
    定义字符串数组
    ifconfig 修改IP
    空指针与野指针的区别
    GDB和Core Dump使用笔记
    雅虎(ycsb)测试hbase(压测)
    decode函数的几种用法
    NVL函数:空值转换函数
    hive行转列,列转行
    case when then else end用法
    hive中一般取top n时,row_number(),rank,dense_ran()常用三个函数
  • 原文地址:https://www.cnblogs.com/nanjolno/p/15101236.html
Copyright © 2011-2022 走看看