• Codeforces Round #649 (Div. 2)


    传送门

    A. XXXXX

    维护一个关于模(x)的前缀和就行。

    Code
    /*
     * Author:  heyuhhh
     * Created Time:  2020/6/13 23:07:56
     */
    #include <iostream>
    #include <algorithm>
    #include <cstring>
    #include <cstdio>
    #include <vector>
    #include <cmath>
    #include <set>
    #include <map>
    #include <queue>
    #include <iomanip>
    #include <assert.h>
    #include <functional>
    #include <numeric>
    #define MP make_pair
    #define fi first
    #define se second
    #define pb push_back
    #define sz(x) (int)(x).size()
    #define all(x) (x).begin(), (x).end()
    #define INF 0x3f3f3f3f
    #define Local
    #ifdef Local
      #define dbg(args...) do { cout << #args << " -> "; err(args); } while (0)
      void err() { std::cout << std::endl; }
      template<typename T, typename...Args>
      void err(T a, Args...args) { std::cout << a << ' '; err(args...); }
      template <template<typename...> class T, typename t, typename... A> 
      void err(const T <t> &arg, const A&... args) {
      for (auto &v : arg) std::cout << v << ' '; err(args...); }
    #else
      #define dbg(...)
    #endif
    using namespace std;
    typedef long long ll;
    typedef pair<int, int> pii;
    //head
    const int N = 1e5 + 5;
     
    void run() {
        int n, x; cin >> n >> x;
        vector <int> a(n);
        for (int i = 0; i < n; i++) {
            cin >> a[i];
            a[i] %= x;
        }
        vector <int> sum(n);
        sum[0] = a[0];
        for(int i = 1; i < n; i++) {
            sum[i] = (sum[i - 1] + a[i]) % x;
        }
        int last = -1;
        int ans = -1;
        for (int i = 0; i < n; i++) {
            if (sum[i] != 0) {
                ans = i + 1;
            } else if (last != -1) {
                ans = max(ans, i - last);
            }
            if (sum[i] > 0 && last == -1) {
                last = i;
            }
        }
        cout << ans << '
    ';
    }
     
    int main() {
        ios::sync_with_stdio(false);
        cin.tie(0); cout.tie(0);
        cout << fixed << setprecision(20);
        int T; cin >> T; while(T--)
        run();
        return 0;
    }
    

    B. Most socially-distanced subsequence

    显然我们最后的选择一定选择连续上升/下降的端点,在中间的点选择对答案不会有贡献并且会增加序列长度。
    所以简单枚举判断一下就行。

    Code
    /*
     * Author:  heyuhhh
     * Created Time:  2020/6/13 23:14:56
     */
    #include <iostream>
    #include <algorithm>
    #include <cstring>
    #include <cstdio>
    #include <vector>
    #include <cmath>
    #include <set>
    #include <map>
    #include <queue>
    #include <iomanip>
    #include <assert.h>
    #include <functional>
    #include <numeric>
    #define MP make_pair
    #define fi first
    #define se second
    #define pb push_back
    #define sz(x) (int)(x).size()
    #define all(x) (x).begin(), (x).end()
    #define INF 0x3f3f3f3f
    #define Local
    #ifdef Local
      #define dbg(args...) do { cout << #args << " -> "; err(args); } while (0)
      void err() { std::cout << std::endl; }
      template<typename T, typename...Args>
      void err(T a, Args...args) { std::cout << a << ' '; err(args...); }
      template <template<typename...> class T, typename t, typename... A> 
      void err(const T <t> &arg, const A&... args) {
      for (auto &v : arg) std::cout << v << ' '; err(args...); }
    #else
      #define dbg(...)
    #endif
    using namespace std;
    typedef long long ll;
    typedef pair<int, int> pii;
    //head
    const int N = 1e5 + 5;
     
    void run() {
        int n; cin >> n;
        vector <int> a(n);
        for (int i = 0; i < n; i++) {
            cin >> a[i];
        }
        vector <int> b;
        b.push_back(a[0]);
        for (int i = 1, j; i < n; i = j) {
            j = i;
            if (a[j] < a[j - 1]) {
                while (j < n && a[j] < a[j - 1]) ++j;
                b.push_back(a[j - 1]);
            } else {
                while (j < n && a[j] > a[j - 1]) ++j;
                b.push_back(a[j - 1]);           
            }
        }
        cout << sz(b) << '
    ';
        for (auto it : b) {
            cout << it << ' ';
        }
        cout << '
    ';
    }
     
    int main() {
        ios::sync_with_stdio(false);
        cin.tie(0); cout.tie(0);
        cout << fixed << setprecision(20);
        int T; cin >> T; while(T--)
        run();
        return 0;
    }
    

    C. Ehab and Prefix MEXs

    题意:
    给定一个序列(a)(0leq a_ileq i,a_ileq a_{i+1})
    现在要构造出一个序列(b),使得对于每个(i),都有

    • (MEX({b_1,b_2,cdots,b_i})=a_i)

    输出(b)序列。

    思路:
    注意到若(a_i ot ={a_{i+1}}),那么(b_{i+1}=a_i)。因此我们首先可以将这些位置确定。
    并且若(1)~(i)不含(a_i),那么(MEX({b_1,b_2,cdots,b_i})leq a_i)。那么我们现在所考虑的是让前缀(MEX)尽量大并且不包含(a_i)。这样直接贪心构造一下就行。
    因为题目条件,显然至少存在一组合法解。
    代码如下:

    Code
    /*
     * Author:  heyuhhh
     * Created Time:  2020/6/15 9:28:17
     */
    #include <iostream>
    #include <algorithm>
    #include <cstring>
    #include <cstdio>
    #include <vector>
    #include <cmath>
    #include <set>
    #include <map>
    #include <queue>
    #include <iomanip>
    #include <assert.h>
    #include <functional>
    #include <numeric>
    #define MP make_pair
    #define fi first
    #define se second
    #define pb push_back
    #define sz(x) (int)(x).size()
    #define all(x) (x).begin(), (x).end()
    #define INF 0x3f3f3f3f
    #define Local
    #ifdef Local
      #define dbg(args...) do { cout << #args << " -> "; err(args); } while (0)
      void err() { std::cout << std::endl; }
      template<typename T, typename...Args>
      void err(T a, Args...args) { std::cout << a << ' '; err(args...); }
      template <template<typename...> class T, typename t, typename... A> 
      void err(const T <t> &arg, const A&... args) {
      for (auto &v : arg) std::cout << v << ' '; err(args...); }
    #else
      #define dbg(...)
    #endif
    using namespace std;
    typedef long long ll;
    typedef pair<int, int> pii;
    //head
    const int N = 1e6 + 5;
     
    bool del[N];
    int n;
    int a[N], b[N];
     
    void run() {
        memset(b, -1, sizeof(b));
        cin >> n;
        for (int i = 1; i <= n; i++) {
            cin >> a[i];
        }
        for (int i = 2; i <= n; i++) {
            if (a[i] != a[i - 1]) {
                del[a[i - 1]] = true;
                b[i] = a[i - 1];
            }
        }
        del[a[n]] = true;
        int m = 0;
        for (int i = 1; i <= n; i++) if (b[i] == -1) {
            while (del[m]) ++m;
            b[i] = m++;
        }
        for (int i = 1; i <= n; i++) {
            cout << b[i] << " 
    "[i == n];
        }
    }
     
    int main() {
        ios::sync_with_stdio(false);
        cin.tie(0); cout.tie(0);
        cout << fixed << setprecision(20);
        run();
        return 0;
    }
    

    D. Ehab's Last Corollary

    和之前一道题很想,找环我们可以直接通过(dfs)树来找。
    如果不存在环那么直接按照深度分层即可。
    注意奇数层和偶数层都有可能成为答案。

    Code
    /*
     * Author:  heyuhhh
     * Created Time:  2020/6/14 0:25:26
     */
    #include <iostream>
    #include <algorithm>
    #include <cstring>
    #include <cstdio>
    #include <vector>
    #include <cmath>
    #include <set>
    #include <map>
    #include <queue>
    #include <iomanip>
    #include <assert.h>
    #include <functional>
    #include <numeric>
    #define MP make_pair
    #define fi first
    #define se second
    #define pb push_back
    #define sz(x) (int)(x).size()
    #define all(x) (x).begin(), (x).end()
    #define INF 0x3f3f3f3f
    #define Local
    #ifdef Local
      #define dbg(args...) do { cout << #args << " -> "; err(args); } while (0)
      void err() { std::cout << std::endl; }
      template<typename T, typename...Args>
      void err(T a, Args...args) { std::cout << a << ' '; err(args...); }
      template <template<typename...> class T, typename t, typename... A> 
      void err(const T <t> &arg, const A&... args) {
      for (auto &v : arg) std::cout << v << ' '; err(args...); }
    #else
      #define dbg(...)
    #endif
    using namespace std;
    typedef long long ll;
    typedef pair<int, int> pii;
    //head
    const int N = 1e5 + 5;
     
    vector <int> G[N];
    int n, m, k;
    int deep[N], father[N];
    vector <int> d[N];
     
    int t;
    vector <int> cyc;
     
    void find(int u, int v) {
        while (u != v) {
            cyc.push_back(u);
            u = father[u];
        }
        cyc.push_back(v);
    }
     
    void dfs(int u, int fa) {
        father[u] = fa;
        deep[u] = deep[fa] + 1;
        d[deep[u]].push_back(u);
        for (auto v : G[u]) if (v != fa) {
            if (deep[v] == -1) {
                dfs(v, u);
            } else if (deep[u] > deep[v]) {
                if (deep[u] - deep[v] + 1 <= k) {
                    if (t == 2) continue;
                    t = 2;
                    find(u, v);
                }
            }
        }
    }
     
    void run() {
        memset(deep, -1, sizeof(deep));
        cin >> n >> m >> k;
        for (int i = 1; i <= m; i++) {
            int u, v; cin >> u >> v;
            G[u].push_back(v);
            G[v].push_back(u);
        }
        dfs(1, 0);
        if (t == 2) {
            cout << 2 << '
    ';
            cout << sz(cyc) << '
    ';
            for (auto it : cyc) {
                cout << it << ' ';
            }
            cout << '
    ';
            return;
        }
        vector <int> ans;
        int need = (k + 1) / 2;
        for (int i = 0; i <= n && need; i += 2) {
            for (auto it : d[i]) {
                ans.push_back(it);
                if (--need == 0) {
                    break;
                }
            }
        }
        if (need) {
            need = (k + 1) / 2;
            ans.clear();
            for (int i = 1; i <= n && need; i += 2) {
                for (auto it : d[i]) {
                    ans.push_back(it);
                    if (--need == 0) {
                        break;
                    }           
                }
            }
        }
        cout << 1 << '
    ';
        for (auto it : ans) {
            cout << it << ' ';
        }
        cout << '
    ';
    }
     
    int main() {
        ios::sync_with_stdio(false);
        cin.tie(0); cout.tie(0);
        cout << fixed << setprecision(20);
        run();
        return 0;
    }
    

    E. X-OR

    题意:
    交互题。
    现在有(0...n-1)的排列(p),每次可以询问两个位置(i,j),会回答(p_i|p_j)
    现在至多询问(4269)次要求得到排列(p)(nleq 2048)

    思路:
    这个题和之前有个每次可以询问一个集合的最大值有相似之处(貌似只是题意比较类似?)。
    首先一看这个询问次数很容易发现我们询问大概(2n+c)次,并且也很容易发现如果我们知道(0)的位置,那么其余的数可以直接求出来。
    接下来的任务就是大概(n+c)次猜出(0)的位置,然后直接得到其余位置的数。
    有比较暴力的方法:

    • 每次随机选择一个数(p_i),并询问其余在集合(S)中的数,找到所有的(p_j&p_i=p_j)(j),并且找到(p_i|p_j)最小的(val),那么容易发现(val=p_i)。然后将(S)清空将得到的下标集合放入(S)中。不断重复此过程。最后会剩下两个数,一个为(0),一个为(2^t),再通过随机找到(0)即可。

    但遗憾的是上述方法的操作次数较多,通过的几率不大。
    不过这种方法可以进行改进:

    • 将之前的随机选择一个数该为随机选择两个数进行询问,若(p_i|p_j)的二进制位数不超过(frac{logn}{2}),那么就选择这个数然后执行上面类似的操作。

    这样就得到了优化,并且我们每次可以将一个大小为(n)的集合变为大小为(sqrt{n})的集合。因为我们选择(p_i),其中二进制为(1)的个数小于一半,假设为(frac{logn}{2}),那么其子集个数为(2^{frac{logn}{2}}=sqrt{n})。这样我们就能得到一个比较稳定的方法,并且很容易发现根号的收敛速度还是比较快的,次数也不会超出。

    当然上面的做法有点巧妙,有一个更加普遍的做法,就是利用或运算的性质,我们可以通过(logn)次询问获得(p_i)的值。具体就是我们求出(z_0,z_1,cdots,z_10)(z_i)表示第(i)为二进制数为(0)的下标。那么通过(p_i)(z_i)的询问即可得到第(i)位的(01)情况。
    之后我们还是借用一开始暴力的思想,但是我们现在因为已经知道了(p_i),所以可以直接确定一个数是否为(p_i)的子集(并不需要对所有遍历一遍去找(val)了)。那么如果(p_j&p_i=p_j),直接令新的(val=p_j)即可。

    两种做法都很巧妙!感觉二进制好多好多trick...(n ightarrow sqrt{n})这里也应该是第一次见吧?
    代码如下:

    Code
    /*
     * Author:  heyuhhh
     * Created Time:  2020/6/15 10:16:32
     */
    #include <iostream>
    #include <algorithm>
    #include <cstring>
    #include <cstdio>
    #include <vector>
    #include <cmath>
    #include <set>
    #include <map>
    #include <queue>
    #include <iomanip>
    #include <assert.h>
    #include <functional>
    #include <numeric>
    #include <random>
    #define MP make_pair
    #define fi first
    #define se second
    #define pb push_back
    #define sz(x) (int)(x).size()
    #define all(x) (x).begin(), (x).end()
    #define INF 0x3f3f3f3f
    #define Local
    #ifdef Local
      #define dbg(args...) do { cout << #args << " -> "; err(args); } while (0)
      void err() { std::cout << std::endl; }
      template<typename T, typename...Args>
      void err(T a, Args...args) { std::cout << a << ' '; err(args...); }
      template <template<typename...> class T, typename t, typename... A> 
      void err(const T <t> &arg, const A&... args) {
      for (auto &v : arg) std::cout << v << ' '; err(args...); }
    #else
      #define dbg(...)
    #endif
    using namespace std;
    typedef long long ll;
    typedef pair<int, int> pii;
    //head
    const int N = 1e5 + 5;
     
    mt19937 rnd(time(NULL));
     
    void run() {
        int n; cin >> n;
        auto query = [&] (int i, int j) {
            cout << "? " << i << ' ' << j << endl;
            int x; cin >> x;
            return x;
        };
        
        int high;
        for (int i = 11; i >= 0; i--) {
            if ((n - 1) >> i & 1) {
                high = i + 1;
                break;
            }
        }
        vector <int> z(high, -1);
        while (count(all(z), -1)) {
            int i = rand() % n + 1, j = rand() % n + 1;
            if (i == j) continue;
            int val = query(i, j);
            for (int k = 0; k < high; k++) {
                if (!(val >> k & 1)) {
                    z[k] = i;
                }
            }
        }
     
        auto get = [&](int p) {
            int res = 0;
            for (int i = 0; i < high; i++) {
                if (z[i] == p) continue;
                int val = query(z[i], p);
                if (val >> i & 1) {
                    res += 1 << i;
                }
            }
            return res;
        };
        
        
        vector <int> ans(n, -1);
        int zero = 1;
        int val = get(1);
        ans[0] = val;
        for (int i = 2; i <= n; i++) {
            int v = query(zero, i);
            if ((v & val) == v) {
                zero = i;
                val = get(i);
                ans[i - 1] = val;
            }
        }
        for (int i = 1; i <= n; i++) {
            if (ans[i - 1] == -1) {
               ans[i - 1] = query(zero, i);
            } 
        }
        cout << "!";
        for (auto it : ans) {
            cout << ' ' << it;
        }
    }
     
    int main() {
        ios::sync_with_stdio(false);
        cin.tie(0); cout.tie(0);
        cout << fixed << setprecision(20);
        run();
        return 0;
    }
    
  • 相关阅读:
    angular2中*ngFor同时适用*ngIf
    win10 正确安装node-sass方式
    ios10禁止用户缩放
    ubuntu切换全屏
    编译scss文件夹
    清除select中的三角形(下拉)
    js中的!!
    scss封装css3兼容性
    js获取当前时间
    Sql Server 数据分页
  • 原文地址:https://www.cnblogs.com/heyuhhh/p/13143581.html
Copyright © 2020-2023  润新知