zoukankan      html  css  js  c++  java
  • CF 1430 (Div.2)

    $ ext{A}$

    依次暴力枚举 $3$ ,$5$ 的窗户个数,最后看能不能被 $7$ 整除即可

    $code$ :

    #include<cstdio>
    #include<cctype>
    
    inline int read(){
        int r=0,f=0;
        char c;
        while(!isdigit(c=getchar()))f|=(c=='-');
        while(isdigit(c))r=(r<<1)+(r<<3)+(c^48),c=getchar();
        return f?-r:r;
    }
    
    inline bool check(int n){
        for(int i=0;i<=n;i+=5)
            if(!((n-i)%7))return true;
        return false;
    }
    
    inline void print(int n){
        for(int i=0;i<=n;i+=5)
            if(!((n-i)%7)){
                printf("%d %d",i/5,(n-i)/7);
                return;
            }
    }
    
    inline void work(){
        int n=read();
        for(int i=0;i<=n;i+=3)
            if(check(n-i)){
                printf("%d ",i/3);
                print(n-i);
                puts("");
                return;
            }
        puts("-1");
    }
    
    int main(){
        int t=read();
        while(t--)work();
        return 0;
    }

    $ ext{B}$

    排个序以后答案就是前 $k+1$ 大的和

    $code$ :

    #include<cstdio>
    #include<cctype>
    #include<algorithm>
    
    using namespace std;
    
    #define maxn 202202
    
    inline int read(){
        int r=0,f=0;
        char c;
        while(!isdigit(c=getchar()))f|=(c=='-');
        while(isdigit(c))r=(r<<1)+(r<<3)+(c^48),c=getchar();
        return f?-r:r;
    }
    
    int n,k,a[maxn];
    
    long long ans;
    
    inline void work(){
        ans=0;
        n=read(),k=read();
        for(int i=1;i<=n;i++)a[i]=read();
        sort(a+1,a+1+n);
        for(int i=0;i<=k;i++)ans+=a[n-i];
        printf("%lld
    ",ans);
    }
    
    int main(){
        int t=read();
        while(t--)work();
        return 0;
    }

    $ ext{C}$

    将 $n$ 与 $n-2$ 合并,造出一个 $n-1$ ,然后将两个 $n-1$ 合并为一个

    然后就 $n-1$ 与 $n-3$ 合并,造出 $n-2$ ,再拿它与 $n-4$ 合并,一直搞下去就可以搞到 $2$ 了

    然后要注意特判 $n=2$

    $code$ :

    #include<cstdio>
    #include<cctype>
    
    #define maxn 202202
    
    inline int read(){
        int r=0,f=0;
        char c;
        while(!isdigit(c=getchar()))f|=(c=='-');
        while(isdigit(c))r=(r<<1)+(r<<3)+(c^48),c=getchar();
        return f?-r:r;
    }
    
    int n,a[maxn],ans[maxn][2];
    
    inline void work(){
        n=read();
        if(n==2){
            puts("2
    1 2");
            return;
        }
        ans[1][0]=n-2,ans[1][1]=n;
        ans[2][0]=ans[2][1]=n-1;
        for(int i=n-1;i>=3;i--)ans[n-i+2][0]=i-2,ans[n-i+2][1]=i;
        printf("2
    ");
        for(int i=1;i<n;i++)
            printf("%d %d
    ",ans[i][0],ans[i][1]);
    }
    
    int main(){
        int t=read();
        while(t--)work();
        return 0;
    }

    $ ext{D}$

    把每一段相同的缩成一个( $e.g.   1110011110->3241$ )

    当删第 $i$ 号点的时候,分类讨论(其实可以写成一类):

    1. 若 $len_i = 1$ ( $len_i$ 即该段还剩下的大小)时,先往后找第一个 $j$ 满足 $len_j > 1$ ,然后让 $len_j--$ (即删掉这段中的一个),$i++$ ,若找不到满足条件的 $j$ ,则说明后面的段大小全都是 $1$ ,删了一个以后还会因为规则删掉一个,此时 $i+=2$
    2. 若 $len_i > 1$ 时,直接 $i++$ 即可

    $code$ :

    #include<cstdio>
    #include<cctype>
    
    #define maxn 202202
    
    inline int read(){
        int r=0,f=0;
        char c;
        while(!isdigit(c=getchar()))f|=(c=='-');
        while(isdigit(c))r=(r<<1)+(r<<3)+(c^48),c=getchar();
        return f?-r:r;
    }
    
    int n,m,ans,len[maxn];
    
    char s[maxn];
    
    inline void work(){
        ans=0;
        n=read(),m=0;
        scanf("%s",s+1);
        len[++m]=1;
        for(int i=2;i<=n;i++){
            if(s[i]!=s[i-1])len[++m]=0;
            len[m]++;
        }
        int i=1,j=1;
        while(i<=m){
            ans++;
            while(j<i)j++;
            while(j<=m&&len[j]<2)j++;
            if(j>m)i+=2;
            else i++,len[j]--;
        }
        printf("%d
    ",ans);
    }
    
    int main(){
        int t=read();
        while(t--)work();
        return 0;
    }

    $ ext{E}$

    首先有一个结论,对于相同的字母,若我们给他们编号,那么 $reverse$ 完后相对顺序肯定不会变(因为没必要交换两个相同的)

    所以我们可以算出每个位置最后所对应的位置 $p_i$ ,又因为每次交换相邻两个,且要把 $p$ 变成 $1,2,3,...,n$ ,可以想到最小次数就是逆序对个数,求一下就好了

    $code$ :

    #include<cstdio>
    #include<cctype>
    
    #define maxn 202202
    
    #define lowbit(k) (k&(-k))
    
    inline int read(){
        int r=0,f=0;
        char c;
        while(!isdigit(c=getchar()))f|=(c=='-');
        while(isdigit(c))r=(r<<1)+(r<<3)+(c^48),c=getchar();
        return f?-r:r;
    }
    
    char s[maxn];
    
    long long ans;
    
    int n,s_w[33],p[maxn],c[maxn],w[33][maxn];
    
    inline void add(int k){
        for(;k<=n;k+=lowbit(k))c[k]++;
    }
    
    inline int sum(int k){
        int s=0;
        for(;k;k-=lowbit(k))s+=c[k];
        return s;
    }
    
    int main(){
        n=read();
        scanf("%s",s+1);
        for(int i=1;i<=n;i++){
            int num=s[i]-'a'+1;
            w[num][++s_w[num]]=i;
        }
        for(int i=1;i<=26;i++)
            for(int j=1;j<=s_w[i];j++)
                p[w[i][j]]=n-w[i][s_w[i]-j+1]+1;
        for(int i=1;i<=n;i++){
            add(p[i]);
            ans+=i-sum(p[i]);
        }
        printf("%lld
    ",ans);
        return 0;
    }

    $ ext{F}$

    好题, $DP$ 和贪心都可以, $DP$ 似乎是 $O(n^2)$ 甚至 $O(n^2logn)$ ,可以通过本题,不过较为复杂,这里考虑贪心。

    很明显,最优的应该是能不换弹就不换,但是对于当前一波,后面的都会影响到这一波的决策,所以考虑从后往前先预处理一下 $need_i$ 表示原本弹夹里的子弹至少要多少才能打完第 $i-n$ 波

    然后预处理完以后能不换就不换,每次弹夹里剩余的子弹经过一波以后就是 $bullet=k-(a_i-bullet)%k$ ,但要考虑一种特殊情况:当 $bullet > a_i $ 时, 直接 $bullet-=a_i$ 即可(不过总结起来也可以写成 $bullet=(k-(a_i-bullet)%k))%k$ ,这里利用了一下 C++ 取模的性质)

    $code$ :

    #include<cstdio>
    #include<cctype>
    
    #define maxn 2222
    
    #define lowbit(k) (k&(-k))
    
    inline int read(){
        int r=0,f=0;
        char c;
        while(!isdigit(c=getchar()))f|=(c=='-');
        while(isdigit(c))r=(r<<1)+(r<<3)+(c^48),c=getchar();
        return f?-r:r;
    }
    
    inline long long max(long long a,long long b){
        return a>b?a:b;
    }
    
    int n,k,l[maxn],r[maxn],a[maxn],need[maxn];
    
    long long ans;
    
    int main(){
        n=read(),k=read();
        for(int i=1;i<=n;i++)
            l[i]=read(),r[i]=read(),a[i]=read();
        for(int i=n;i>=1;i--){
            int ned=a[i];
            if(r[i]==l[i+1])ned+=need[i+1]; 
            if(ned>1ll*(r[i]-l[i]+1)*k)return puts("-1"),0;
            need[i]=max(ned-1ll*(r[i]-l[i])*k,0);
        }
        int had=0;
        for(int i=1;i<=n;i++){
            if(had<need[i]){
                ans+=had;
                had=k;
            }
            ans+=a[i];
            had=had<a[i]?k-(a[i]-had)%k:had-a[i];
        }
        printf("%lld
    ",ans);
        return 0;
    }
  • 相关阅读:
    Typora的使用
    selenium中webdriver提供的八大定位元素方法
    JAVA的Data和Timestamp的相互转换
    Jmeter设置参数作为断言依据
    Springboot +Poi 导入Excel表格
    window.location.reload();
    带参数的链接跳转
    Layui结束时间不能小于开始时间
    后台返回数据渲染Layui表格
    Layui中layedit模板的使用
  • 原文地址:https://www.cnblogs.com/wyzwyz/p/13811564.html
Copyright © 2011-2022 走看看