Codeforces Round #153 (Div. 2)

之前觉得没必要,现在觉得以后还是记录一下做的CF吧...虽然刷的不多


A. Little Xor

水题,直接三层for循环暴力


B.Unsorting Array

题目大意:给一个序列(可能是有序的,也可能是无序的), 要求交换位置不同并且不相等的两个数,使得这个序列变成无序。如果不能,输出-1.

我的思路

这题当时WA了很多次都没出,之后重测,目测有200+的人也掉了。。。这题确实很考验人的思维的缜密性。

如果这个序列不同的数大于等于3个的话,那么,我们就挑出这个序列中三个不同的数出来,只需要“破坏”这三个数的顺序,让它们变成无序的,就可以保证整个序列变成无序的。

如果只有2个不同的数,那么有几个情况要特判的:

2 2 0

2 3 3

1 2 1 2

如果只有1个不同的数,那么肯定无解。


代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<set>
#define STOP puts("haha");
#define REP(i,n) for(int i=0; i<(n); ++i)
using namespace std;

typedef long long int64;
const int MAXN = 1000005;
int arr[MAXN], n;

int judge(){ 
    set<int>ss;
    REP(i, n){
        ss.insert(arr[i]);
        if(ss.size() == 3) return 3;
    }
    return ss.size();
}

int main(){
    int cas=1;
    while(~scanf("%d", &n)){
        REP(i, n) scanf("%d", &arr[i]);
        int cnt = judge();
        if(n<=2 || cnt == 1) {
            puts("-1");
        }
        else if(cnt == 2){
            bool ok=false;
            for(int i=1; i<n-1; ++i) {
                if(arr[i] != arr[i-1] && arr[i]==arr[i+1]){
                    ok=true;
                    printf("%d %d\n", i, i+1);
                    break;
                }
                if(arr[i]==arr[i-1] && arr[i]!=arr[i+1]){
                    ok=true;
                    printf("%d %d\n", i+1, i+2);
                    break;
                }
                if(i<n-3 && arr[i]==arr[i+2] && arr[i+1]==arr[i+3] && arr[i]!=arr[i+1]){
                    ok=true;
                    printf("%d %d\n", i+1, i+2);
                    break;
                }
            }
            if(!ok) puts("-1");
        }
        else{
            int pos[3], cur=0;
            pos[0] = 0;
            for(int i=1; i<n && cur<=2; ++i){
                bool ok=true;
                for(int j=0; j<=cur; ++j){
                    if(arr[i]==arr[pos[j]]){
                        ok=false;
                        break;
                    }
                }
                if(ok){
                    pos[++cur] = i;
                }
            }
            int a=arr[pos[0]], b=arr[pos[1]], c=arr[pos[2]];
            if(a>b&&b>c || a<b&&b<c){
                printf("%d %d\n", pos[1]+1, pos[2]+1);
            }
            else if(a>b&&b<c || a<b&&b>c){
                printf("%d %d\n", pos[0]+1, pos[2]+1);
            }
        }
    }
    return 0;
}

C.Points on Line

题目大意:给一个递增的序列,要求出有多少个3个数的组合,使得这3个数最大与最小的数之差不超过d。

我的思路:

枚举“区间”的最右一个数x3, 然后找到以这个数为最大数的组合,它的最小值x3-d(即最左点)在那里,可以发现这个区间的组合都是满足条件的。然后根据一点的数学知识,可以求出这个区间共有多少种组合。假设最左点位置在left和最右点在right,那么这两点之内共有n = right-left-1个数, 那么再根据一点组合数学知识,可以求出有n*(n-1)/2总组合。

枚举最右点for一遍,那么找“左点”可以用二分,也可以维护一个指针值。


代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define REP(i,n) for(int i=0; i<(n); ++i)
using namespace std;

typedef long long int64;
const int MAXN = 1000005;
int arr[MAXN];

int main(){
    int n, d;
    while(~scanf("%d%d", &n,&d)){
        REP(i, n) scanf("%d", &arr[i]);
        
        int64 ans=0;
        for(int i=2; i<n; ++i){
            int *p = lower_bound(arr, arr+i, arr[i]-d);
            int64 t = i-(p-arr+1);
            t = t*(t+1)/2;
            ans += t;
        }
        cout << ans << endl;
    }
    return 0;
}


D. Two Sets

E. Tree and Table


原创http://blog.csdn.net/shuangde800 (转载请标明)



你可能感兴趣的:(codeforces)