zoukankan      html  css  js  c++  java
  • Codeforces Round #736 (Div. 2)

    Codeforces Round #736 (Div. 2)

    A. Gregor and Cryptography

    • 题意

    给出一个p, 让你找到x,y令 (x%p = y%p)

    • 思路

    签到思维,想一下mod p = 1的情况就行

    code :

    void solve(){
        int n;
        cin >> n;
        if(n == 5) {
            cout << "2 4" << endl;
            return;
        }
        cout << "2 " << n / 2 << endl;
    }
    

    B. Gregor and the Pawn Game

    • 题意

    给一个棋盘,给出的第一行是敌人的,第二行是自己的,敌人不动,我们自己可以进行两个操作

    1. 当上方的没有敌人的棋子,直接占用即可
    2. 当敌人的棋子在左上或右上的时候,可以选择移至敌人的棋子位子,并吃掉它
    • 思路

    贪心, 优先拿左边的,中间的,右边的,记录一下是否用过即可

    code :

    char a[N], b[N];
    bool st[N];
    void solve(){
        int n;
        cin >> n;
        for(int i = 1;i <= n;i ++ ) st[i] = 0;
        cin >> (a + 1) >> (b + 1);
        int ans = 0;
        for(int i = 1;i <= n;i ++)  {
            if(a[i] == '1') {
                if(b[i - 1] == '1' && !st[i - 1]) ans ++;
                else if(i + 1 <= n && b[i + 1] == '1') {
                    ans ++;
                    st[i + 1] = 1;
                }
            }else if(b[i] == '1' && !st[i]) {
                ans ++;
                st[i] = 1;
            }
        }
        cout << ans << endl;
    }
    

    C. Web of Lies

    • 题意

    给出一个图,每个人及一个点,且当前点的权值为它自己的编号((w_i = i)),当一个人相连的另一个人的权值大于他时,他会死,求最后剩下几个人
    三种操作

    1. 增加一条边((u o v))
    2. 删除一条边((u o v)), 保证存在
    3. 查询当前剩下几个人
    • 思路

    建边后,记录每个人相邻的人中有多少个大于他本身的点,那么只有当所有大于他权值的点和他连的边全删了,他才能活,这里用set进行处理删除和增加边的操作,O(logn)

    code :

    
    int st[N];
    
    void solve(){
        int n,m;
        cin >> n >> m;
        for(int i = 1;i <= n;i ++) st[i] = 0;
        int ans = n;
        while(m --) {
            int a,b;
            cin >> a >> b;
            if(a > b) swap(a,b);
            if(!st[a]) {
                ans --;
            }
            st[a]++;
        }
        int k;
        cin >> k;
        fep(i,1,k) {
            int op;
            cin >> op;
            if(op == 1) {
                int a,b;
                cin >> a >> b;
                if(a > b) swap(a,b);
                if(!st[a]) {
                    ans --;
                }
                st[a]++;
            }else if(op == 2) {
                int a,b;
                cin >> a >> b;
                if(a > b) swap(a,b);
                st[a] --;
                if(!st[a]) ans ++;
            }else {
                cout << ans << endl;
            }
        }
    }
    

    D. Integers Have Friends

    • 题意

    给出一个长度为 n 的序列,让你求一个最大长度的连续子序列中 (a_i mod m = a_{i + 1} mod m = ···· a_j mod m) , (i -> j), 输出最大的长度

    • 思路

    发现差分数组中,某个区间的gcd != 1时,那么这个区间是可以的,那么更新答案。
    用st表处理区间gcd,双指针处理左右端点 或 枚举左端点二分长度来处理区间都行。

    code :

    // ST表处理
    int lg[N]; // lg函数记录(int)log(i)
    int st[30][N]; // st表,计算st[len][l]的最小值的下标
    int n;
    int a[N], b[N];
    
    // 处理
    void buildST() {
        fep(i,2,n - 1) lg[i]=lg[i >> 1] + 1;
        fep(i,1,n - 1) st[0][i] = b[i];
        fep(j,1,lg[n - 1]) // 长度
            for(int i = 1;i < n - (1 << j) + 1;i ++){ // 左端点
                st[j][i] = __gcd(st[j - 1][i],st[j - 1][i + (1 << (j - 1))]);
            }
                
    }
    int get_(int l,int r) {
        int len = lg[r - l + 1];
        return __gcd(st[len][l],st[len][r - (1 << len) + 1]);
    }
    
    void solve(){
        cin >> n;
        fep(i,1,n) cin >> a[i];
        if(n == 1) {
            cout << "1" << endl;
            return;
        }
        fep(i,1,n - 1) b[i] = abs(a[i + 1] - a[i]);
        buildST();
        int ans = 1;
        int j = 1;
        for (int i = 1; i < n; ++i){
            while(j <= i && get_(j,i) == 1) j ++;
            ans = max(ans, i - j + 2);
        }
        cout << ans << endl;
    }
    
  • 相关阅读:
    你必须知道的495个C语言问题,学习体会四
    ++操作符重载代码分析
    正斜杠 与反斜杠之争
    文件操作基础入门
    你必须知道的495个C语言问题,学习体会三
    你必须知道的495个C语言问题,学习体会二
    【皇甫】☀别进来 千万别进来
    【皇甫】☀设计_模式
    【皇甫】☀七个小矮人和一个小博
    【皇甫】☀游戏还有游戏还是游戏
  • 原文地址:https://www.cnblogs.com/darker-wxl/p/15089046.html
Copyright © 2011-2022 走看看