• Educational Codeforces Round 121 (Rated for Div. 2)思路分享


    这次的cf(虽然已经过去了很久...)C题就挂了好久,最后还是没有搞出来.....气死...
    (幸好这次网站崩了,没有记rating....)
    Educational Codeforces Round 121 (Rated for Div. 2)

    A. Equidistant Letters

    A题简单构造,我们直接将相同的字母放一起即可。

    B. Minor Reduction

    B题给定一个很大的数字,要求做一个操作使得相邻的两位替换成两个相加的结果。
    首先我们优先考虑它的位数不变,经过简单的思考,发现如果要位数不变的话,(即加起来的和>=10)发现加起来之后这个数一定是减小的(和原来相比)。既然一定要减小,所以我们倒着找,看能不能找到相邻的两个位相加使得他们的和>9.
    之后若找不到,说明只能减小一位,但这个情况和上面情况相反,相加之后虽然位数减少了但是数增大了或不变,所以我们直接让第一位和第二位相加即可。

    C. Monsters And Spells

    首先我们考虑只有一个怪物时,最优的策略就是从k[i]-h[i]+1开始施法,在k[i]时正好以h[i]打败怪物。考虑有两个怪物怎么办,我们设start[i]为怪物i能够正好打败怪物的开始施时间。若start[i+1]>k[i],则两个怪物不影响,我们分别独立的施法打败。若start[i+1]<k[i]的话,这个时候我们将两个怪兽在一个连续施法区间开始打败,而开始的时间就是两个怪兽开始时间的小的值。就按照正常的顺序来做的话,会发现很难的确定如何的合并与统计答案,因为开始时间的无序性,造成很大的麻烦。所以我们不妨将开始时间从小到大进行排序。这样的话,我们只需要知道上一个的开始时间即可。(排序的重要性...)

    #include<bits/stdc++.h>
    #define ll long long
    using namespace std;
    const int N=110;
    int T,n,k[N],h[N],st[N];
    vector<pair<int,int>>ve;
    inline ll f(int l,int r)
    {
        return (ll)(r-l+2)*(r-l+1)/2;
    }
    int main()
    {
    //    freopen("1.in","r",stdin);
        scanf("%d",&T);
        while(T--)
        {
            scanf("%d",&n);
            for(int i=1;i<=n;++i) scanf("%d",&k[i]);
            for(int i=1;i<=n;++i) scanf("%d",&h[i]);
            ve.clear();
            for(int i=1;i<=n;++i) ve.push_back({k[i]-h[i]+1,k[i]});
            sort(ve.begin(),ve.end());
            ll ans=0;
            int sta=0,pos=0;
            for(int i=0;i<ve.size();++i)
            {
                st[i]=ve[i].first; 
                if(i==0||st[i]>pos) 
                {
                    ans+=f(st[i],ve[i].second);
                    sta=st[i];pos=ve[i].second;
                }
                else
                {
                    if(ve[i].second<pos) continue;
                    ans-=f(sta,pos);
                    pos=ve[i].second;
                    ans+=f(sta,pos);
                }
            }
            printf("%lld\n",ans);
        }
        return 0;
    } 
    
    D. Martial Arts Tournament

    这个题在没有看题解的情况下,我竟然想出了个线段树优化DP的方法....(妈妈这没点码力是不行的...)
    果然我的思维还是不太全面吧....
    考虑这个题,首先我们可以先将权值排序计数,这样之后他们之间的数值大小就没有意义了,我们令\(b_i\)表示排名第i的数的个数。我们直接在\(b_i\)上进行划分就不用考虑合不合法的问题了。由于这个题是将这个序列分成三个集合。那么我们肯定是要枚举的其中的集合的。其实我的第一想法就是直接枚举到哪是第一个集合...这根本没有用到2的次幂的条件。既然是枚举集合大小,那么我们根据题意,最优的方法就是枚举答案中的那个2的几次幂,考虑怎么枚举,枚举哪些集合。若枚举中间集合的话,我们还是要考虑划分问题的。所以我们枚举两边集合的大小。之后考虑两边怎么取,这里有个贪心的策略。尽可能的在不超过枚举的集合的情况下,多取。因为我们不够的我们是一定要付出代价的。我们从中间集合将一定数量给左边集合的话,对于中间集合的答案,如果最优解的情况就是必须要那些块的话,你直接付出代价即可,和我们左边因为不够而拿的直接抵消,而且这也有可能使得中间的集合更优。(反正使得中间集合的选择更多了。)或者考虑再最优解的情况下,我们左边拿了a个,最多可以再拿k个,但最优的情况是没有拿,那么我们拿了答案仍不变。

    #include<bits/stdc++.h>
    #define ll long long
    using namespace std;
    const int N=2e5+10;
    int n,T,a[N],b[N],ans=1e9,num;
    inline int f(int x)
    {
        for(int i=0;i<=20;++i) 
        {
            if(x==(1<<i)) return 0;
            if((1<<i)>x) return (1<<i)-x;
        }
    }
    inline void work(int n1,int n2)
    {
        int l=num+1,r=0,sum1=0,sum2=0,sum3=0;
        for(int i=1;i<=num;++i)
        {
            if(sum1+b[i]<=(1<<n1)) sum1+=b[i];
            else {l=i;break;}
        }
        for(int i=num;i>=l;--i)
        {
            if(sum2+b[i]<=(1<<n2)) sum2+=b[i];
            else {r=i;break;}
        }
        for(int i=l;i<=r;++i) sum3+=b[i];
        ans=min(ans,f(sum3)+(1<<n1)-sum1+(1<<n2)-sum2);
    }
    int main()
    {
    //    freopen("1.in","r",stdin);
        scanf("%d",&T);
        while(T--)
        {
            scanf("%d",&n);
            for(int i=1;i<=n;++i) scanf("%d",&a[i]);
            sort(a+1,a+n+1);
            num=0;ans=1e9;
            for(int i=1;i<=n;++i)
            {
                if(a[i]==a[i-1]) b[num]++;
                else b[++num]=1;
            }
            for(int i=0;i<=20;++i)
                for(int j=0;j<=20;++j) work(i,j);
            printf("%d\n",ans);     
        }
        return 0;
    } 
    
  • 相关阅读:
    《摄像头 —— MIPI CSI2简介》
    《notepad++批量在任意行以及任意位置添加相同字符》
    《摄像头 —— sensor移植以及调试》
    条款18:让接口容易被正确使用,不易被误用
    条款20:宁以 passbyreferencetoconst 替换 passbyvalue
    第13章 运行时类型信息
    两个MATLAB函数dir2par和cplxcomp
    业务连续性计划
    语音识别之——音频特征fbank与mfcc,代码实现与分析
    在logo上面实现类似闪电的动画效果
  • 原文地址:https://www.cnblogs.com/gcfer/p/15835194.html
Copyright © 2020-2023  润新知