Codeforces Round #153 (Div. 2)

A.

暴力, 水题

B.

 n <= 2 都输出-1, 其它必然存在一对满足题意的数, 而且 这对数相邻, 注意到这点的话,就容易做多了,直接暴力找解

View Code
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int a[100005], b[100005];
int main()
{
    int i, j, n;
    scanf("%d", &n);
    for(i = 0; i < n ;i++)
        scanf("%d", &a[i]), b[i] = a[i];
    if(n <= 2) { puts("-1"); return 0;}
    sort(b, b+n);
    for(i = 0; i < n-1; i++)
    {
        if(a[i] == a[i+1])
             continue;
        swap(a[i], a[i+1]);

        for(j = 0; j < n && a[j] == b[j]; j++); //如果换了是顺序或逆序再换回来
        if(j == n) { swap(a[i], a[i+1]); continue; }
        for(j = 0; j < n && a[j] == b[n-j-1]; j++);
        if(j == n) { swap(a[i], a[i+1]); continue; }
        printf("%d %d\n", i+1, i+2); return 0;
    }
    puts("-1");
}

C.

单调队列( two points)

View Code
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
#define LL __int64
int a, n, d;
LL ans;
queue <int> q;
int main() 
{
    int i, j;
    scanf("%d%d", &n, &d);
    for(i = 0; i < n; i++)
    {
        scanf("%d", &a);
        q.push(a);
        while(q.front()  < q.back() - d) q.pop();
        j = q.size()-1;
        ans += (LL)j * (j-1)/2;
    }
    printf("%I64d\n", ans);
}

二分

View Code
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define LL __int64
int d, n;
int a[100005];
LL ans;
int main()
{
    int i, j;
    scanf("%d%d", &n, &d);
    for(i = 0; i < n; i++)
        scanf("%d", &a[i]);
    for(i = 1; i < n; i++)
        j = i - (lower_bound(a, a+i, a[i] - d) - a),
        ans += (LL)j *(j-1)/2;
    printf("%I64d\n", ans);
    return 0;
}

D.

注意两个操作的关系,做一次操作1和一次操作2就会回到原来的序列, 分别求出只做操作1和只做操作2就能回到原来序列的周期a,b

根据a,b和给定的k能得出结论

View Code
#include<cstdio>
#include<cstring>
int q[103], p[103], s[103], pp[103];
int n, k, a, b;
int main()
{
    int i, j;
    scanf("%d%d", &n, &k);
    for(i = 1; i <= n; i++)
        scanf("%d", &q[i]);
    for(i = 1; i <= n; i++)
        scanf("%d", &s[i]);
    //求解操作1的周期
    for(i = 1; i <= n; i++)
        pp[i] = p[i] = i;
    while(a <= k)
    {
        for(j = 1; j <= n && p[j] == s[j]; j++);
        if(j == n+1) break;      
        for(j = 1; j <= n; j++)
            pp[j] = p[q[j]];
        for(j = 1; j <= n; j++)
            p[j] = pp[j];
        a++;
    }
    //求解操作2的周期
    for(i = 1; i <= n; i++)
        pp[i] = p[i] = i;
    while(b <= k)
    {
        for(j = 1; j <= n && p[j] == s[j]; j++);
            if(j == n+1) break;
        for(j = 1; j <= n; j++)
            pp[q[j]] = p[j];
        for(j = 1; j <= n; j++)
            p[j] = pp[j];
        b++;
    }
    //对两边周期都为1进行特判
    if(a == 1 && b == 1 && k == 1) puts("YES");  
    else if(a == 1 && b == 1) puts("NO"); 

    else if(a == k+1 && b == k+1) puts("NO");   // 两边都走不到
    else if(!a && !b) puts("NO");               //一开始的串就是目标(a == 0 && b == 0)
        
    else if(((b+k+1)&1) || ((a+k+1)&1)) puts("YES"); //左右只要有一边可以到达
    else puts("NO");
    return 0;
}

E.

周期为t = 360360(2到15的最小公倍数), 想了很久就是不知道为什么,求大神证明。

View Code
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define LL __int64
const LL t = 360360;
LL a, b, k;
LL min(LL a, LL b) { return a < b ? a : b; }
LL gao(LL a, LL b)
{
    LL c = 0;
    while(a != b)
    {
        LL tp = a-1;
        for(int i = 2; i <= k; i++)
            if(a/i*i >= b)
                tp = min(tp, a/i*i);
        c++;
        a = tp;
    }
    return c;
}
int main()
{
    scanf("%I64d%I64d%I64d", &a, &b, &k);
    if(a/t == b/t)
        printf("%I64d\n", gao(a%t, b%t));
    else
        printf("%I64d\n", gao(a%t, 0) + gao(t, b%t) + (a/t-b/t-1)*gao(t, 0));
}

 

posted @ 2012-12-13 20:32  To be an ACMan  Views(198)  Comments(0)    收藏  举报