• 3月21日考试 题解(数据结构+区间DP+贪心)


    前言:T3写挂了,有点难受。

    ---------------

    T1 中位数

    题意简述:给你一段长度为$n$的序列,分别输出$[1,2k-1]$的中位数$(2k-1leq n)$。

    -------------

    其实正解是用两个堆分别为大根堆和小根堆。但我这里偷了个懒,直接由STL函数upper_bound二分查找插入数字(STL大法好

    Code:

    #include<bits/stdc++.h>
    using namespace std;
    vector<int> v;
    int n;
    int main()
    {
        scanf("%d",&n);
        for (int i=1;i<=n;i++)
        {
            int x;
            scanf("%d",&x);
            v.insert(upper_bound(v.begin(),v.end(),x),x);
            if (i%2==1)
                printf("%d
    ",v[(i-1)/2]);    
        }    
        return 0;
    } 

    T2 多边形

    题意简述:给你一个有n个边的多边形,每个顶点上有一个数字,每条边上为$+$或$ imes $ .现在去掉任意一条边,求运算的最大值.

    --------------

    这道题其实跟石子合并有点像,不过有一点要注意:1.子区间的合并受运算符号限制;2.可能有负数,所以我们同时要维护最小值,因为有可能负乘负大于当前数.

    题目细节较多.

    Code:

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn=55;
    int f[maxn*2][maxn*2][maxn*2],mf[maxn*2][maxn*2][maxn*2];
    int ch[maxn*2],a[maxn*2];
    int n,ans=-0x3f3f3f3f;
    int maxx(int a,int b,int c,int d,int e)
    {
        return max(a,max(b,max(c,max(d,e))));
    }
    int minn(int a,int b,int c,int d,int e)
    {
        return min(a,min(b,min(c,min(d,e))));
    }
    int main()
    {
        scanf("%d",&n);
        for (int i=1;i<=n;i++)
            for (int j=1;j<=n*2;j++)
                for (int k=1;k<=n*2;k++) f[i][j][k]=-0x3f3f3f3f,mf[i][j][k]=0x3f3f3f3f;
        for (int i=1;i<=2*n;i++)
        {
            if (i%2==1){
                char c;cin>>c;
                if (c=='t') ch[i/2+1]=1;
                else ch[i/2+1]=2;        
            }
            else cin>>a[i/2];
        }
        for (int i=n+1;i<=n*2;i++)
        {
            a[i]=a[i-n];
            ch[i]=ch[i-n];
        }
        for (int i=1;i<=n;i++)
            for (int j=1;j<=n*2;j++) f[i][j][j]=mf[i][j][j]=a[j];
        for (int i=1;i<=n;i++)
        {
            for (int len=2;len<=n;len++)
            {
                for (int j=i;j<=i+n-1;j++)
                {
                    int k=j+len-1;
                    if (k>=i+n) break;
                    for (int l=j;l<k;l++)
                    {
                        if (ch[l+1]==1) {
                            f[i][j][k]=max(f[i][j][k],f[i][j][l]+f[i][l+1][k]);
                            mf[i][j][k]=min(mf[i][j][k],mf[i][j][l]+mf[i][l+1][k]);
                        }
                        else{
                            f[i][j][k]=maxx(f[i][j][k],f[i][j][l]*f[i][l+1][k],f[i][j][l]*mf[i][l+1][k],mf[i][j][l]*f[i][l+1][k],mf[i][j][l]*mf[i][l+1][k]);
                            mf[i][j][k]=minn(mf[i][j][k],f[i][j][l]*f[i][l+1][k],f[i][j][l]*mf[i][l+1][k],mf[i][j][l]*f[i][l+1][k],mf[i][j][l]*mf[i][l+1][k]);
                        }
                    }
                }
            }
            ans=max(ans,f[i][i][i+n-1]);
        }
        printf("%d",ans);
        return 0;
    } 

    T3 连锁店

    题意简述:张三开了$n$个连锁店,每个连锁店能用$a_{i}$个空瓶换$b_{i}$瓶水.每个店都可以无限次兑换,现在李四有$s$瓶水,求最多的兑换次数.如果不存在输出$-1$.

    $nleq 100000$,$s,a_{i},b_{i}leq 10^{19}$.

    ---------------------

    无解的情况:当$sgeq a_{i}$并且$a_{i}leq b_{i}$.在输入的时候顺便判断.

    我们考虑贪心:以$a_{i}-b_{i}$作为关键字排序很显然差值越小,兑换次数越多.

    记得开$unsigned$ $long$ $long$.

    Code:

    #include<bits/stdc++.h>
    using namespace std;
    typedef unsigned long long ll;
    const int maxn = 1e5+7,mod = 1e9+7;
    struct node{ll x,y,z;}a[maxn];
    bool operator < (const node a,const node b){    
        if(a.z != b.z)return a.z < b.z;    
        return a.x<b.x;
    }
    int main()
    {   
        int n,flag = 0;    ll s,ans = 0;    
        scanf("%d%llu",&n,&s);    
        for(int i=0;i<n;i++){        
            scanf("%llu%llu",&a[i].x,&a[i].y);        
            if(a[i].x>s)n--,i--;
            else if(a[i].x<=a[i].y)flag = 1;        
            a[i].z = a[i].x-a[i].y;  
         }    
        if(flag)return 0*puts("-1");    
        sort(a,a+n);    
        for(int i=0;i<n;i++){        
        if(s>=a[i].x){            
             ll tmp = (s-a[i].x)/a[i].z+1;           
            ans += tmp;            
             s -= tmp*a[i].z;        
        }  
        printf("%llu
    ",ans);    
        return 0;  
    }    
         
  • 相关阅读:
    NOIP知识点&&模板整理【更新中】
    qbxt DAY7 T4
    qbxt DAY7 T2
    qbxt DAY 6 T3 柯西不等式和拉格朗日不等式
    qbxt DAY4 T4
    qbxt DAY4 T3
    #98. 表达式计算 杂想
    扫描线入门学习笔记 (主要讲解代码实现)
    学OI要知道的基础知识(咕咕咕)
    主定理学习笔记(总结向)
  • 原文地址:https://www.cnblogs.com/Invictus-Ocean/p/12543037.html
Copyright © 2020-2023  润新知