zoukankan      html  css  js  c++  java
  • UVA

    题目:

    把1~n(n≤500)放到一个圆盘里,每个数恰好出现一次。每次可以选4个连续的数字翻转顺序。问能不能变成1.2.3....n的顺序。

    思路:

    这样的题的规律真的是一点都不好推,看了网上的博客知道只有n为奇数且给出的序列的逆序数为奇数的时候,这种情况下是不能完成的,其余的情况都可以。

    如果n为偶数,那么在这个环中总有4个连续的数字的逆序数是偶数,假设4个数的逆序数是x,翻转之后逆序数变成了6-x(为什么是6-x自己还没有搞懂),逆序数的变化为6-2x为偶数。最后升序的逆序数是0为偶数。根据偶数+(-)偶数=偶数,奇数+(-)偶数=奇数,可以得知当序列的逆序数为偶数时,那就可以通过翻转是逆序数变为0.

    代码:

    树状数组求逆序数

    #include <bits/stdc++.h>
    #define inf 0x3f3f3f3f
    #define MAX 1e3
    #define FRE() freopen("in.txt","r",stdin)
    #define FRO() freopen("out.txt","w",stdout)
    using namespace std;
    typedef long long ll;
    typedef pair<int, int> P;
    const int maxn = 600;
    int a[maxn],n,tree[maxn];
    
    int lowbit(int x){
        return x&(-x);
    }
    
    void add(int x){
        while(x<=n){
            tree[x]++;
            x += lowbit(x);
        }
    }
    
    int getSum(int x){
        int res = 0;
        while(x>0){
            res+=tree[x];
            x -= lowbit(x);
        }
        return res;
    }
    
    int main(){
        //FRE();
        int kase;
        scanf("%d",&kase);
        while(kase--){
            memset(tree,0,sizeof(tree));
            scanf("%d",&n);
            int cnt = 0;
            for(int i=0; i<n; i++){
                scanf("%d",&a[i]);
                add(a[i]);
                cnt += i+1-getSum(a[i]);
            }
            if(cnt%2==1 && n%2==1){
                printf("impossible
    ");
            }else{
                printf("possible
    ");
            }
        }
        return 0;
    }

    暴力求逆序数

    #include <bits/stdc++.h>
    #define inf 0x3f3f3f3f
    #define MAX 1e3
    #define FRE() freopen("in.txt","r",stdin)
    #define FRO() freopen("out.txt","w",stdout)
    using namespace std;
    typedef long long ll;
    typedef pair<int, int> P;
    const int maxn = 600;
    int a[maxn],n;
    
    int main(){
        int kase;
        scanf("%d",&kase);
        while(kase--){
            scanf("%d",&n);
            for(int i=0; i<n; i++){
                scanf("%d",&a[i]);
            }
            int cnt = 0;
            for(int i=1; i<n; i++){
                for(int j=0; j<i; j++){
                    if(a[j]>a[i]){
                        cnt++;
                    }
                }
            }
            if(cnt%2==1 && n%2==1){
                printf("impossible
    ");
            }else{
                printf("possible
    ");
            }
        }
        return 0;
    }
  • 相关阅读:
    第二次冲刺 03
    第二次冲刺 02
    第二次冲刺 01
    程序员修炼三部曲阅读笔记03
    程序员修炼三部曲阅读笔记02
    团队项目计划会议
    课堂练习—购书
    构建之法阅读笔记03
    学习进度条十二
    课堂作业找水王2
  • 原文地址:https://www.cnblogs.com/sykline/p/10347773.html
Copyright © 2011-2022 走看看