【線段樹】CSU_1555_Inversion Sequence

1555: Inversion Sequence
Time Limit: 2 Sec Memory Limit: 256 MB
Submit: 478 Solved: 173

Description
For sequence i1, i2, i3, … , iN, we set aj to be the number of members in the sequence which are prior to j and greater to j at the same time. The sequence a1, a2, a3, … , aN is referred to as the inversion sequence of the original sequence (i1, i2, i3, … , iN). For example, sequence 1, 2, 0, 1, 0 is the inversion sequence of sequence 3, 1, 5, 2, 4. Your task is to find a full permutation of 1~N that is an original sequence of a given inversion sequence. If there is no permutation meets the conditions please output “No solution”.

Input
There are several test cases.
Each test case contains 1 positive integers N in the first line.(1 ≤ N ≤ 10000).
Followed in the next line is an inversion sequence a1, a2, a3, … , aN (0 ≤ aj < N)
The input will finish with the end of file.

Output
For each case, please output the permutation of 1~N in one line. If there is no permutation meets the conditions, please output “No solution”.

Sample Input
5
1 2 0 1 0
3
0 0 0
2
1 1

Sample Output
3 1 5 2 4
1 2 3
No solution

題意:
設有一個1~n的全排列,滿足給定輸入的逆序對數(shù),求這個全排列。
例如:輸入5 1 2 0 1 0,即求一個1~5的全排列,滿足,1有一個逆序對(即1的前面有且只有1個數(shù)字大于它),2有兩個逆序對(即2前面有且只有2個數(shù)字大于它),3有零個逆序對(3前面沒有數(shù)字大于它),以此類推??傻? 1 5 2 4。

思路:
模擬這個過程,樣例5 1 2 0 1 0中,1前面有1個數(shù)字大于它,又因為1是1~n中最小,序列中所有數(shù)字都大于它,即1前面只能有一個數(shù)字,則1前面留一個空位,即1在從左往右數(shù)第2個空位插入,得
_ 1 _ _ _ _
2前面有2個數(shù)字大于它,除去1,2在1~n中又最小,同理,2前面留兩個空位,在第3個空位插入,得
_ 1 _ 2 _ _
3前面沒有數(shù)字大于它,同理除去1、2,3是1~n中最小,則3前面留零個空位,在第1個空位插入,得
3 1 _ 2 _
4前面有1個數(shù)字大于它,同理,4前面留一個空位,在第2個空位插入,得
3 1 _ 2 4
5前面沒有數(shù)字大于它,在第1個空位插入,得
3 1 5 2 4
得到結果3 1 5 2 4。
即從1開始到n,每一個數(shù)字都去考慮,留幾個空位給后面比它大的數(shù)字,那么就要實時更新每一段區(qū)間空位的數(shù)量,使用線段樹。

#include<cstdio>
#include<cstring>
using namespace std;

const int maxn = 20000 + 5;
int tree[maxn * 4];
int buf[maxn];
int ans[maxn];

// 更新線段樹
void Update(int root) {
    tree[root] = tree[root * 2] + tree[root * 2 + 1];
    return;
}

// 遞歸構造線段樹
void Build(int root, int l, int r) {
    if (l == r) {
        tree[root] = 1;
        return;
    }
    int mid = (l + r) / 2;
    Build(root * 2, l, mid);
    Build(root * 2 + 1, mid + 1, r);
    Update(root);
    return;
}

// 找到位置插入數(shù)字
int Insert(int val, int root, int l, int r) {
    if (l == r) {
        tree[root] = 0;
        return l;
    }
    int mid = (l + r) / 2;
    int ret;
    if (tree[root << 1] >= val)
        ret = Insert(val, root * 2, l, mid);
    else
        ret = Insert(val - tree[root * 2], root * 2 + 1, mid + 1, r);
    Update(root);
    return ret;
}

int main() {
    int n;
    while (scanf("%d", &n) != EOF) {
        // memset(tree, 0, sizeof(tree));
        Build(1, 1, n);
        bool noSolution = false;
        for (int i = 1; i <= n; ++i)
            scanf("%d", buf + i);
        for (int i = 1; i <= n; ++i) {
            // 任何時候空位數(shù)小于所給逆序對數(shù),即當前數(shù)字沒位置插入,則無解
            if (tree[1] <= buf[i]) {
                noSolution = true;
                break;
            }
            // 在第buf[i]+1個位置插入i
            ans[Insert(buf[i] + 1, 1, 1, n)] = i;
        }
        if (noSolution)
            printf("No solution\n");
        else {
            for (int i = 1; i < n; ++i)
                printf("%d ", ans[i]); 
            printf("%d\n", ans[n]);
        }
    }
    return 0;
}

最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

  • 背景 一年多以前我在知乎上答了有關LeetCode的問題, 分享了一些自己做題目的經(jīng)驗。 張土汪:刷leetcod...
    土汪閱讀 12,891評論 0 33
  • 字丑是不能言說的艱難………自己還是比較滿意,畢竟我是文科生不是美術生。 最后花瓣的紋理沒畫好………
    槿冉閱讀 466評論 0 1
  • 大學生活,余額不足,即將透支。 下午看過書,陪閨蜜去健身房去玩耍了。 畢竟,身體與靈魂,要統(tǒng)一戰(zhàn)線,否則,總感覺偷...
    666上古小白羊閱讀 473評論 2 3
  • 最近,大家都被一個臨產(chǎn)產(chǎn)婦帶著未出生的胎兒在醫(yī)院跳樓的事件刷屏,家屬和醫(yī)院現(xiàn)在責任問題爭執(zhí)不下,雙方都互指對方不肯...
    碧水書香閱讀 194評論 0 1

友情鏈接更多精彩內(nèi)容