洛谷 - P1338 - 末日的传说 - 打表

https://www.luogu.org/problemnew/show/P1338
先打表看了一下规律,居然看出来n的位置是阶梯往前的.而每个阶梯的头头,必有后半段降序.
再仔细看一下居然每次交换后半段的没被交换过的元素和前半段的最后一个元素.
打了一个表,不清楚复杂度就交了,当时以为是n²的,因为逆序数最多有 \(C_n^2\) 但最后事实证明不是.

因为一开始找阶梯是n的,找到之后这个阶梯的长度最多也是n的,其实复杂度是两个n.

附带打表代码以及表:

#include<bits/stdc++.h>
using namespace std;
#define ll long long

int main(){
    int n;
    while(cin>>n){
        vector<int> v;
        for(int i=1;i<=n;i++)
            v.push_back(i);
        int maxcnt=-1;
        do{
            int cnt=0;
            for(int i=0;i<n;i++){
                for(int j=i+1;j<n;j++){
                    if(v[i]>v[j]){
                        cnt++;
                    }
                }
            }
            if(cnt>maxcnt){
                for(int i=0;i<n;i++)
                    printf("%d ",v[i]);
                printf(" cnt=%d\n",cnt);
                maxcnt=cnt;
            }
        }while(next_permutation(v.begin(),v.end()));
    }
}
5
1 2 3 4 5  cnt=0
1 2 3 5 4  cnt=1
1 2 4 5 3  cnt=2
1 2 5 4 3  cnt=3
1 3 5 4 2  cnt=4
1 4 5 3 2  cnt=5
1 5 4 3 2  cnt=6
2 5 4 3 1  cnt=7
3 5 4 2 1  cnt=8
4 5 3 2 1  cnt=9
5 4 3 2 1  cnt=10

6
1 2 3 4 5 6  cnt=0
1 2 3 4 6 5  cnt=1
1 2 3 5 6 4  cnt=2
1 2 3 6 5 4  cnt=3
1 2 4 6 5 3  cnt=4
1 2 5 6 4 3  cnt=5
1 2 6 5 4 3  cnt=6
1 3 6 5 4 2  cnt=7
1 4 6 5 3 2  cnt=8
1 5 6 4 3 2  cnt=9
1 6 5 4 3 2  cnt=10
2 6 5 4 3 1  cnt=11
3 6 5 4 2 1  cnt=12
4 6 5 3 2 1  cnt=13
5 6 4 3 2 1  cnt=14
6 5 4 3 2 1  cnt=15

然后是构造表的代码:

#include<bits/stdc++.h>
using namespace std;
#define ll long long

int ans[50005];
int pos[50005];

int main(){
    ll n,m;
    while(cin>>n>>m){
        //for(int cm=0;cm<=n*(n-1)/2;cm++){
            //ll m=cm;
            for(int i=1;i<=n;i++){
                ans[i]=i;
                pos[i]=i;
            }

            /*if(m==0){
                for(int i=1;i<=n;i++)
                    printf("%d%c",ans[i]," \n"[i==n]);
                continue;
            }*/

            ll sum=0;
            int p=0;
            while(sum<=m){
                p++;
                sum+=p;
            }

            sum-=p;
            p--;

            for(int i=0;i<=p;i++){
                ans[n-i]=(n-(p-i));
                pos[n-(p-i)]=i;
            }

            /*for(int i=1;i<=n;i++)
                printf("%d ",ans[i]);
            printf("\n");*/

            int curchange=n;
            while(m>sum){
                swap(ans[n-p-1],ans[curchange]);
                m--;
                curchange--;
            }

            for(int i=1;i<=n;i++)
                printf("%d ",ans[i]);
            printf("\n");

            //cout<<sum<<endl;
        //}
    }
}

猜你喜欢

转载自www.cnblogs.com/Yinku/p/10691968.html
今日推荐