• Codeforces Round #672 (Div. 2)


    原题链接

    题外话

    恢复性训练

    A

    题意

    问你一组数列排成非递减的数列, 是否在$ n * (n-1)/2-1 $次数中完成

    思路

    妈妈的, 我把自己演了,写了个假代码
    直接判断这个数组是否是单调递减的,是的话输出no ,否则输出yes ,至于为什么,可以画个图理解一下(很简单的图,我就不管了)

    代码

    #include <cstdio>
    #include <algorithm>
    #include<iomanip>
    #include <iostream>
    #include <cmath>
    #include <string>
    #include <vector>
    #include <set>
    #include <queue>
    #include <cstring>
    #include<stack>
    #include <cassert>
    #include<map>
    #define cl(x) memset(x,0,sizeof(x))
    #define rep(i,a,b) for(i=a;i<=b;i++)
    #define drep(i,a,b) for(i=a;i>=b;i--)
    #define em(x) emplace(x)
    #define emb(x) emplace_back(x)
    #define emf(x) emplace_front(x)
    #define fi first
    #define se second
    #define pb push_back
    #define de(x) cerr<<#x<<" = "<<x<<endl
    #define __i __int128
    #define pn printf("
    ");
    #define pk printf(" ");
    #define p(n) printf("%d",n);
    #define pln(n) printf("%d
    ",n);
    #define s(n) scanf("%d",&n);
    #define ss(n) scanf("%s",n);
    #define ps(n) printf("%s",n);
    #define sld(n) scanf("%lld",&n);
    #define pld(n) printf("%lld",n);
    #define slf(n) scanf("%lf",&n);
    #define plf(n) printf("%lf",n);
    #define sc(n) scanf("%c",&n);
    #define pc(n) printf("%c",n);
    #define dbg(x...) do { cout << "33[32;1m" << #x << " -> "; err(x); } while (0)
    
    using namespace std;
    //using namespace __gnu_pbds;
    typedef long long LL;
    typedef pair<int,int> pii;
    typedef pair<LL,LL> pLL;
    const int inf=0x7fffffff;
    const int N =3.1e5;
    const int maxn = 200010;
    
    void clear(unsigned char *pta, int size )
    {//结构体初始化
        while(size>0)
        {
            *pta++ = 0;
            size --;
        }
    }
    
    LL   n, k, m ;
    LL ar[N],br[N],cr[200005],dr[200005];
    LL i,j,g;
    LL MOD = 998244353 ;
    
    
    LL fac[N],inv_fac[N];
    
    //快速幂
    LL qpow(LL x, LL y ){
        x%=MOD;
        long long res=1%MOD;
        while(y){
            if(y&1)res=res*x%MOD;
            y>>=1;
            x=x*x%MOD;
        }
        return res;
    
    }
    
    void pre(){
        fac[0] =1 ;
        for(int i=1;i<N;i++){
            fac[i] =fac[i-1] * i %MOD;
        }
        inv_fac[N - 1 ] = qpow(fac[N - 1] , MOD-2 ) ;
    
        for(int i =N-2 ;i>=0 ;i--){
            inv_fac[i] = inv_fac[i+1] * (i+1) %MOD;
        }
    
    }
    
    LL C (LL a ,LL b){
        if(a<0 || b> a )//因为是C(a,b) 所以b《= a
        {
            return 0;
        }
    
        return fac[a] * inv_fac[b] % MOD *inv_fac[a-b]%MOD;//a 的阶乘 / ( b的阶乘 * (a-b的阶乘))
    
    }
    void answer(){
       sld(n);LL cnt =0 ;
       for(int i=1;i<=n;i++)sld(ar[i]);
       for(int i=1;i<=n;i++){
            if(ar[i]>ar[i+1] && i+1<=n ){
                cnt ++ ;
            }
       }
       if(cnt == n-1 )printf("NO
    ");
       else printf("YES
    ");
    
     }
    
    
    int main()
    {
    //    ios::sync_with_stdio(0);
    //    cin.tie(0), cout.tie(0);
    //       pre();
        int t;s(t);
        while(t--)
            answer();
    
    
        return 0;
    
    }
    
    
    

    B

    题意

    给你一串数, 然后让你找出来 两个数的& 大于等于 两个数的xor 的数量

    思路

    一看有xor 和 & 一定要想到 二进制 , 然后通过二进制下的数字,发现 & 的 >= xor 只能是当 两个数字的最大位置的 1 位置相同才行。
    所以存一下每个数的 最大位置上的 1 的位置 ,然后求和即可

    代码

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <vector>
    #include <math.h>
    #include <string.h>
    #include <algorithm>
    #include <iostream>
    #include <string>
    #include <sstream>
    #include <iostream>
    #include <time.h>
    #include <queue>
    #include <list>
    #include <map>
    #include <set>
    #include <vector>
    #include <stack>
    #include <string.h>
    #include <bitset>
    #define sf scanf
    #define pf printf
    #define lf double
    #define p123 printf("123
    ");
    #define pn printf("
    ");
    #define pk printf(" ");
    #define p(n) printf("%d",n);
    #define pln(n) printf("%d
    ",n);
    #define s(n) scanf("%d",&n);
    #define ss(n) scanf("%s",n);
    #define ps(n) printf("%s",n);
    #define sld(n) scanf("%lld",&n);
    #define pld(n) printf("%lld",n);
    #define slf(n) scanf("%lf",&n);
    #define plf(n) printf("%lf",n);
    #define sc(n) scanf("%c",&n);
    #define pc(n) printf("%c",n);
    //#define gc getchar();
    #define ll long long
    #define re(n,a) memset(n,a,sizeof(n));
    #define len(a) strlen(a)
    #define eps 1e-13
    #define zero(x) (((x) > 0? (x):(-x)) < eps)
    using namespace std;
    
    
    int a[100050];
    int b[1000];
    #include <stdio.h>
    int main(){
        int T;
        s(T)
        while(T --){
            int n;
            s(n)
            re(b,0);
            for(int i = 0; i < n; i ++){
                s(a[i])
                int flag = 0;
                while(a[i] != 0){
                    a[i] >>= 1;
                    flag ++;
                }
                b[flag] ++;
            }
            ll sum = 0ll;
            for(int i = 0; i < 50; i ++){
                ll temp = b[i];
                sum += (temp*(temp-1ll))>>1;
            }
            pld(sum) pn
        }
        return 0;
    }
    
    

    C1

    题意

    简单版本的就是给你一组数,然后让你找出来这样一个序列 ($ a_1-a_2+a_3-a_4+... +a_n $ )使得 这个结果是最大的情况

    思路

    因为是个简单版本的,可以直接暴力求局部最大和最小, 然后相加一下就行

    代码

    #include <cstdio>
    #include <cstdio>
    #include <algorithm>
    #include<iomanip>
    #include <iostream>
    #include <cmath>
    #include <string>
    #include <vector>
    #include <set>
    #include <queue>
    #include <cstring>
    #include<stack>
    #include <cassert>
    #include<map>
    #define cl(x) memset(x,0,sizeof(x))
    #define rep(i,a,b) for(i=a;i<=b;i++)
    #define drep(i,a,b) for(i=a;i>=b;i--)
    #define em(x) emplace(x)
    #define emb(x) emplace_back(x)
    #define emf(x) emplace_front(x)
    #define fi first
    #define se second
    #define pb push_back
    #define de(x) cerr<<#x<<" = "<<x<<endl
    #define __i __int128
    #define pn printf("
    ");
    #define pk printf(" ");
    #define p(n) printf("%d",n);
    #define pln(n) printf("%d
    ",n);
    #define s(n) scanf("%d",&n);
    #define ss(n) scanf("%s",n);
    #define ps(n) printf("%s",n);
    #define sld(n) scanf("%lld",&n);
    #define pld(n) printf("%lld",n);
    #define slf(n) scanf("%lf",&n);
    #define plf(n) printf("%lf",n);
    #define sc(n) scanf("%c",&n);
    #define pc(n) printf("%c",n);
    #define dbg(x...) do { cout << "33[32;1m" << #x << " -> "; err(x); } while (0)
    
    using namespace std;
    //using namespace __gnu_pbds;
    typedef long long LL;
    typedef pair<int,int> pii;
    typedef pair<LL,LL> pLL;
    const int inf=0x7fffffff;
    const int N =3.1e5;
    const int maxn = 200010;
    
    void clear(unsigned char *pta, int size )
    {//结构体初始化
        while(size>0)
        {
            *pta++ = 0;
            size --;
        }
    }
    
    LL   n, k, m ;
    LL ar[N],br[N],cr[200005],dr[200005];
    LL i,j,g;
    LL MOD = 998244353 ;
    
    
    LL fac[N],inv_fac[N];
    
    //快速幂
    LL qpow(LL x, LL y ){
        x%=MOD;
        long long res=1%MOD;
        while(y){
            if(y&1)res=res*x%MOD;
            y>>=1;
            x=x*x%MOD;
        }
        return res;
    
    }
    
    void pre(){
        fac[0] =1 ;
        for(int i=1;i<N;i++){
            fac[i] =fac[i-1] * i %MOD;
        }
        inv_fac[N - 1 ] = qpow(fac[N - 1] , MOD-2 ) ;
    
        for(int i =N-2 ;i>=0 ;i--){
            inv_fac[i] = inv_fac[i+1] * (i+1) %MOD;
        }
    
    }
    
    LL C (LL a ,LL b){
        if(a<0 || b> a )//因为是C(a,b) 所以b《= a
        {
            return 0;
        }
    
        return fac[a] * inv_fac[b] % MOD *inv_fac[a-b]%MOD;//a 的阶乘 / ( b的阶乘 * (a-b的阶乘))
    
    }
    void answer(){
        sld(n) ;sld(k);
        for(int i=1 ;i<=n;i++)sld(ar[i]);
        ar[0] = ar[n+1 ] =0 ;LL sum =0 ;
        for(int i=1 ;i<=n;i++){
            if(ar[i]>ar[i-1]&&ar[i] >ar[i+1 ])sum +=ar[i];
            if(ar[i]<ar[i-1]&&ar[i] <ar[i+1 ])sum -=ar[i];
        }
        pld(sum);pn;
     }
    
    
    int main()
    {
    //    ios::sync_with_stdio(0);
    //    cin.tie(0), cout.tie(0);
    //       pre();
        int t;s(t);
        while(t--)
            answer();
    
    
        return 0;
    
    }
    
    

    C2

    题意

    这个版本在前面的基础上添加了一个q的移动, 每次都是把两个ar[r] , ar[l] 进行交换位置, 问你交换完之后的结果

    思路

    这个其实要考虑的事情也不多, 因为他是两个数进行交换,

    • 那么假设ar[l] < ar[r] ,那么可能ar[r] 交换之后也是局部最大的,
    • 那么假设ar[l] > ar[r] ,那么可能ar[r] 交换之后也是局部最小的,
    • 所以受这个交换的影响的数, 一共只有ar[l] 和 ar[r] 这两个和他们左右两边的数,
    • 所以,只需要每次先把这两个数和他们左右两边的数先判断一下,是否有局部最大的数或者最小的数, 有的话就从结果中先去掉
    • 之后,在交换完之后, 在进行判断在新位置上的ar[l] , ar[r] 是否是局部最大的数或者最小的数, 是的话再加进来即可

    代码

    #include <cstdio>
    #include <algorithm>
    #include<iomanip>
    #include <iostream>
    #include <cmath>
    #include <string>
    #include <vector>
    #include <set>
    #include <queue>
    #include <cstring>
    #include<stack>
    #include <cassert>
    #include<map>
    #define cl(x) memset(x,0,sizeof(x))
    #define rep(i,a,b) for(i=a;i<=b;i++)
    #define drep(i,a,b) for(i=a;i>=b;i--)
    #define em(x) emplace(x)
    #define emb(x) emplace_back(x)
    #define emf(x) emplace_front(x)
    #define fi first
    #define se second
    #define pb push_back
    #define de(x) cerr<<#x<<" = "<<x<<endl
    #define __i __int128
    #define pn printf("
    ");
    #define pk printf(" ");
    #define p(n) printf("%d",n);
    #define pln(n) printf("%d
    ",n);
    #define s(n) scanf("%d",&n);
    #define ss(n) scanf("%s",n);
    #define ps(n) printf("%s",n);
    #define sld(n) scanf("%lld",&n);
    #define pld(n) printf("%lld",n);
    #define slf(n) scanf("%lf",&n);
    #define plf(n) printf("%lf",n);
    #define sc(n) scanf("%c",&n);
    #define pc(n) printf("%c",n);
    #define dbg(x...) do { cout << "33[32;1m" << #x << " -> "; err(x); } while (0)
    
    using namespace std;
    //using namespace __gnu_pbds;
    typedef long long LL;
    typedef pair<int,int> pii;
    typedef pair<LL,LL> pLL;
    const int inf=0x7fffffff;
    const int N =5e5+10;
    const int maxn = 200010;
    
    void clear(unsigned char *pta, int size )
    {//结构体初始化
        while(size>0)
        {
            *pta++ = 0;
            size --;
        }
    }
    
    LL   n, k, m ;
    LL ar[N],br[N],cr[200005],dr[200005];
    LL i,j,g;
    
    set<int > big_pos , small_pos;
    LL sum;
    bool big(int i){
        return ar[i] >  max(ar[i-1],ar[i+1]);
    }
    bool small(int i){
        return ar[i] < min(ar[i-1] , ar[i+1]);
    
    }
    
    
    void clear_pos(int pos){
    //    cout<<ar[pos]<<endl;
        if(big(pos)&&big_pos.count(pos)){
    
            sum -= ar[pos];
            big_pos.erase(pos);
        }
        if(small(pos)&&small_pos.count(pos)){
    
            sum+=ar[pos];
            small_pos.erase(pos);
        }
    //    cout<<sum<<endl;
    
    }
    void updata(int pos){
    
        if(big(pos)&&!big_pos.count(pos)){
    
            sum += ar[pos];
            big_pos.insert(pos);
        }
        if(small(pos)&&!small_pos.count(pos)){
            sum-=ar[pos];
            small_pos.insert(pos);
        }
    //    cout<<i<<" "<<sum<<endl;
    
    
    }
    void answer(){
        sld(n);sld(k);
        for(int i=1;i<=n;i++)sld(ar[i]);
        sum =0;
        ar[n+1] = 0;
        big_pos.clear();
        small_pos.clear();
        for(int i=1;i<=n;i++){
            updata(i);
        }
        pld(sum);pn;
        for(int i=k;i>=1;i--){
            int x,y ;s(x);s(y);
            clear_pos(x-1);        clear_pos(x);        clear_pos(x+1);
            clear_pos(y-1);        clear_pos(y);        clear_pos(y+1);
            swap(ar[x],ar[y]);
            updata(x-1);        updata(x);        updata(x+1);
            updata(y-1);updata(y);updata(y+1);
            pld(sum);pn;
    
        }
    
        }
    
    
    int main()
    {
    //    ios::sync_with_stdio(0);
    //    cin.tie(0), cout.tie(0);
    
        int t;s(t);
        while(t--)answer();
    
    
        return 0;
    
    }
    
    
    

    D

    题意

    一共n个灯,然后每个灯有自己亮的时间l,r 然后问你是否有k个灯能同时亮着,有的话,求出一共可以选择出来的数量,没有就是0

    思路

    其实就是一个贪心 + 组合数学

    • 首先找出同一时间亮着的灯 (这里需要自己想一个操作, 我是跟一个带佬学的用vector的pair ,设置 l 为 -1 ,r 为 1 , 之后判断second 是- 1 的)
    • 然后 通过组合数 来求出这个时间的数量,
    • 进行求和即可

    代码

    
    #include <cstdio>
    #include <algorithm>
    #include<iomanip>
    #include <iostream>
    #include <cmath>
    #include <string>
    #include <vector>
    #include <set>
    #include <queue>
    #include <cstring>
    #include<stack>
    #include <cassert>
    #include<map>
    #define cl(x) memset(x,0,sizeof(x))
    #define rep(i,a,b) for(i=a;i<=b;i++)
    #define drep(i,a,b) for(i=a;i>=b;i--)
    #define em(x) emplace(x)
    #define emb(x) emplace_back(x)
    #define emf(x) emplace_front(x)
    #define fi first
    #define se second
    #define pb push_back
    #define de(x) cerr<<#x<<" = "<<x<<endl
    #define __i __int128
    #define pn printf("
    ");
    #define pk printf(" ");
    #define p(n) printf("%d",n);
    #define pln(n) printf("%d
    ",n);
    #define s(n) scanf("%d",&n);
    #define ss(n) scanf("%s",n);
    #define ps(n) printf("%s",n);
    #define sld(n) scanf("%lld",&n);
    #define pld(n) printf("%lld",n);
    #define slf(n) scanf("%lf",&n);
    #define plf(n) printf("%lf",n);
    #define sc(n) scanf("%c",&n);
    #define pc(n) printf("%c",n);
    #define dbg(x...) do { cout << "33[32;1m" << #x << " -> "; err(x); } while (0)
    
    using namespace std;
    //using namespace __gnu_pbds;
    typedef long long LL;
    typedef pair<int,int> pii;
    typedef pair<LL,LL> pLL;
    const int inf=0x7fffffff;
    const int N =3.1e5;
    const int maxn = 200010;
    
    void clear(unsigned char *pta, int size )
    {//�ṹ���ʼ��
        while(size>0)
        {
            *pta++ = 0;
            size --;
        }
    }
    
    LL   n, k, m ;
    LL ar[N],br[N],cr[200005],dr[200005];
    LL i,j,g;
    LL MOD = 998244353 ;
    
    
    LL fac[N],inv_fac[N];
    
    //������
    LL qpow(LL x, LL y ){
        x%=MOD;
        long long res=1%MOD;
        while(y){
            if(y&1)res=res*x%MOD;
            y>>=1;
            x=x*x%MOD;
        }
        return res;
    
    }
    
    void pre(){
        fac[0] =1 ;
        for(int i=1;i<N;i++){
            fac[i] =fac[i-1] * i %MOD;
        }
        inv_fac[N - 1 ] = qpow(fac[N - 1] , MOD-2 ) ;
    
        for(int i =N-2 ;i>=0 ;i--){
            inv_fac[i] = inv_fac[i+1] * (i+1) %MOD;
        }
    
    }
    
    LL C (LL a ,LL b){
        if(a<0 || b> a )//����C��a��b�� ����b��= a
        {
            return 0;
        }
    
        return fac[a] * inv_fac[b] % MOD *inv_fac[a-b]%MOD;//a �Ľ׳� / �� b�Ľ׳� * ��a-b�Ľ׳ˣ���
    
    }
    void answer(){
       sld(n);sld(k);
       vector<pii  >v;
       for(int i=1 ;i<=n;i++){
            int l, r ;s(l);s(r);
            v.pb({l,-1});v.pb({r,1});
       }
       sort(v.begin(), v.end());
       LL sum =0  , cnt =0 ;
       for(int i=0;i<v.size();i++){
        sum -= v[i].se;
        if(v[i].se==-1){
            cnt = (cnt + C(sum - 1  , k -1  ))%MOD;
    
    //        cout<<cnt<<" ,"<<sum<<endl;
        }
    //    cout<<sum<<endl ;
       }
       pld(cnt);pn;
     }
    
    
    int main()
    {
    //    ios::sync_with_stdio(0);
    //    cin.tie(0), cout.tie(0);
           pre();
    //    int t;s(t);
    //    while(t--)
            answer();
    
    
        return 0;
    
    }
    
    
  • 相关阅读:
    02
    循环语句的注意点
    unsigned/signed int/char类型表示的数值范围
    C程序设计语言(第二版)--- 习题选
    第一篇来自博客园的博客--哈哈希望大家点赞
    脆弱的GPS系统--摘抄《环球科学》
    【Python入门自学笔记专辑】——函数式编程
    c++标准库conio.h文件
    推荐几个配色和图标网站
    Ajax实现简单下拉选项
  • 原文地址:https://www.cnblogs.com/gaohaoy/p/13733304.html
Copyright © 2020-2023  润新知