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

    这次真心是个坑……

    一开始把A题题意看错了,上来就敲WA了一次,开始心急,之后B题卡了40多分钟,实在无奈跑去看C,发现水题一道,迅速A了之后瞎搞了一下B题,D题看不懂题意,于是Lock了所有代码跑去hack其他人。

    最后只提交了3道。

    System Test之后只有A和C通过了,不过靠着各种hack补了600分勉强把B的损失补上,最终排81,顺利紫名。

    A题 Little Xor

    题目大意:给一个序列,长度不超过100,求任意连续区间异或结果的最大值。

    题解:因为最多也就100个数,所以直接N^2暴力即可。

    View Code
    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #include <cstring>
    #include <set>
    #include <vector>
    #include <queue>
    #include <stack>
    #include <cmath>
    #include <map>
    using namespace std;
    #define INF 0x73737373
    #define EPS 1e-8
    #define lson l, m, rt<<1
    #define rson m+1, r, rt<<1|1
    int a[105];
    int main()
    {
        int n, ret = 0;
        scanf("%d", &n);
        for(int i = 0; i < n; i++)
            scanf("%d", &a[i]);
        for(int i = 0; i < n; i++)
        {
            int temp = 0;
            for(int j = i; j < n; j++)
            {
                temp ^= a[j];
                ret = max(temp, ret);
            }
        }
        printf("%d\n", ret);
        return 0;
    }

    B题 Unsorting Array

    大坑……最后只有200多个人AC……

    题目大意:给一个任意序列,交换其中两个不相同的数字的位置,使其是一个无序的序列。一个序列为升序或降序则认为其有序。

    如果序列初始为无序,依然需要交换两个不同的数字,如果不可能使其变为无序,输出-1,否则输出交换的两个数的序号。

    题解:纯YY,做法仅供参考……

    首先判断输出-1的情况:

    1.如果序列长度小于等于2,必然为-1

    2.如果序列中所有数字相同,必然为-1

    3.如果序列长度等于3,并且开头和结尾的数相同,必然为-1

    上述3个情况中漏掉情况3的很多,我的ROOM里只有2个人对了……

    如果不为-1则必然可以找到两个可以交换的数。

    我们取序列正中间的那个数,然后向左找离它最近的,比它大的数a,比它小的数b。

    同时,向右找离它最近的,比它大的数c,比它小的数d。

    如果左右都能找到比它大的数,那么原序列无序,交换这两个数依然无序。

    如果左右都能找到比它小的数,那么原序列无序,交换这两个数依然无序。

    其他情况原序列可能有序,那么我只要随便交换一下找到的a、b、c、d中的某一个即可破坏有序。

    View Code
    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #include <cstring>
    #include <set>
    #include <vector>
    #include <queue>
    #include <stack>
    #include <cmath>
    #include <map>
    using namespace std;
    #define INF 0x73737373
    #define EPS 1e-8
    #define lson l, m, rt<<1
    #define rson m+1, r, rt<<1|1
    vector<int> ori;
    int main()
    {
        int n;
        scanf("%d", &n);
        bool can = false;
        for(int i = 0; i < n; i++)
        {
            int a;
            scanf("%d", &a);
            ori.push_back(a);
            if(i > 0 && ori[i] != ori[i-1]) can = true;
        }
        if(n == 2)can = false;
        if(n == 3 && ori[0] == ori[2])can = false;
        if(!can) puts("-1");
        else
        {
            int a = INF, b = INF, c = INF, d = INF;
            for(int i = n / 2; i >= 0; i--)
                if(ori[i] > ori[n/2] && a == INF) a = i;
                else if(ori[i] < ori[n/2] && b == INF) b = i;
            for(int i = n / 2; i < n; i++)
                if(ori[i] > ori[n/2] && c == INF) c = i;
                else if(ori[i] < ori[n/2] && d == INF) d = i;
    
            int r1, r2;
            if(a != INF && c != INF && ori[a] != ori[c]) r1 = a, r2 = c;
            else if(b != INF && d != INF && ori[b] != ori[d]) r1 = b, r2 = d;
            else r1 = min(min(min(a, b), c), d), r2 = n / 2;
            printf("%d %d\n", r1 + 1, r2 + 1);
        }
        return 0;
    }

    C题 Point on Line

    题目大意:X轴上有n个点,给定一个d,要求取三个点其中任意两点间的距离<=d,问共有多少种取法。

    题解:很水……

    要求任意两点间的距离小于等于d,其实就是要求最左的点和最右的点的距离不超过d。

    那么对于任意一个点Ai,如果我们把它作为最左的点,

    则我们一定可以找到跟它距离不超过d的最右的点Ar(r >= i),

    这样我们可以在r - i个点内随意选两个,共有Cn2种取法。

    于是枚举每一个点作为最左的点,把取法求和即可。

    View Code
    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #include <cstring>
    #include <set>
    #include <vector>
    #include <queue>
    #include <stack>
    #include <cmath>
    #include <map>
    using namespace std;
    #define INF 0x73737373
    #define EPS 1e-8
    #define lson l, m, rt<<1
    #define rson m+1, r, rt<<1|1
    int a[105000];
    int main()
    {
        int n, d;
        scanf("%d%d", &n, &d);
        for(int i = 1; i <= n; i++)
            scanf("%d", &a[i]);
        __int64 ret = 0, k;
        for(int i = 1; i <= n - 2; i++)
        {
            int index = lower_bound(a, a + n, a[i] + d) - a;
            if(a[index] - a[i] <= d)
                k = index - i;
            else if(a[index - 1] - a[i] <= d)
                k = index - i - 1;
            ret += (k * (k - 1)) / 2;
        }
        printf("%I64d\n", ret);
        return 0;
    }

    D题 Playing with Permutations

     英语拙计……

    题目大意:开始你有三个序列

    一个长度为n的序列p,其初始值是1、2、3、4、5……n-1、n。

    一个长度为n的序列q,其初始值由输入获得。

    一个长度为n的序列s,其初始值由输入获得。

    接下来你必须执行k步操作,每步操作有两种选择。

    1.生成一个新的p,其中newp[i] = p[q[i]]

    2.生成一个新的p,其中newp[q[i]] = p[i]

    要求你在执行的k-1步操作过程中的任意一步,序列p都不得等于序列s。在执行完第k步操作后,序列p等于序列s。

    问这种情况是否可能。

    题解:

    如果把原文的操作一、二完全看懂的话,很容易就可以看出两个操作是互逆,也就是说如果你对p执行了操作1再执行操作2的话,相当于什么也没做。

    知道了这一点就很好处理了。

    如果我们执行m1次 操作1 可以使得序列p等于序列s,那么我们先执行(k - m1) / 2次的(操作1、操作2)组合,再执行m1次 操作1 即可。

    如果我们执行m2次 操作2 可以使得序列p等于序列s,那么我们先执行(k - m2) / 2次的(操作1、操作2)组合,再执行m2次 操作2 即可。

    所以只要求出其中的m1、m2再判断一下k - m1,k - m2是否是偶数就行了。

    View Code
    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #include <cstring>
    #include <set>
    #include <vector>
    #include <queue>
    #include <stack>
    #include <cmath>
    #include <map>
    using namespace std;
    #define INF 0x73737373
    #define EPS 1e-8
    #define lson l, m, rt<<1
    #define rson m+1, r, rt<<1|1
    int p[105], np[105], q[105], r[105];
    bool is_same(int n)
    {
        for(int i = 1; i <= n; i++)
            if(p[i] != r[i]) return false;
        return true;
    }
    void init(int n)
    {
        for(int i = 1; i <= n; i++) p[i] = i;
    }
    int main()
    {
        int n, k;
        scanf("%d%d", &n, &k);
        for(int i = 1; i <= n; i++) scanf("%d", &q[i]);
        for(int i = 1; i <= n; i++) scanf("%d", &r[i]);
        init(n);
        if(is_same(n))puts("NO");
        else
        {
            int head = -1, tail = -1;
            for(int i = 1; i <= k; i++)
            {
                for(int j = 1; j <= n; j++)
                    np[j] = p[q[j]];
                memcpy(p, np, sizeof(p));
                if(is_same(n))
                {
                    head = i;
                    break;
                }
            }
            init(n);
            for(int i = 1; i <= k; i++)
            {
                for(int j = 1; j <= n; j++)
                    np[q[j]] = p[j];
                memcpy(p, np, sizeof(p));
                if(is_same(n))
                {
                    tail = i;
                    break;
                }
            }
            if(head == -1 && tail == -1) puts("NO");
            else if(head == 1 && tail == 1 && k != 1) puts("NO");
            else if(head != -1 && (k - head) % 2 == 0) puts("YES");
            else if(tail != -1 && (k - tail) % 2 == 0) puts("YES");
            else puts("NO");
        }
        return 0;
    }
  • 相关阅读:
    P1117 [NOI2016] 优秀的拆分 SA+DP
    P3346 [ZJOI2015]诸神眷顾的幻想乡 广义SAM
    P3705 [SDOI2017]新生舞会 分数规划+费用流
    P2336 [SCOI2012]喵星球上的点名 SA+树状数组
    543. Diameter of Binary Tree
    451. Sort Characters By Frequency
    563. Binary Tree Tilt
    703. Kth Largest Element in a Stream
    743. Network Delay Time
    kaggle _Titanic: Machine Learning from Disaster
  • 原文地址:https://www.cnblogs.com/deadblue/p/2807095.html
Copyright © 2011-2022 走看看