codeforces problem1214 E Petya and Construction Set(構造)

鏈接

題意:

構造一棵2*n個節點的樹,對於節點2*i-1和節點2*i的距離爲d[i],保證有解



思路:

把奇數的點排在一起組成鏈,然後偶數只需要根據對應那個點的位置和距離算一下要被安排在哪,直接做的話會有些問題。
把每一對[2x-1,x]根據距離排序,優先安排距離大的,如果偶數節點要安排的位置比鏈尾要大了,那麼直接插入一個到鏈尾即可,而且要優先考慮插,其次考慮掛在已有的鏈上。
由於距離是遞減的,每個偶數點要麼可以插入到已有的鏈尾,要麼就必定可以掛在已有鏈上的一個點。

參考代碼:

#include <bits/stdc++.h>
using namespace std;
const int N=1e5+5;

struct node{
    int a,b,v;
    bool operator <(const node &t)const {
        return v>t.v;
    }
}p[N];

int mp[2*N];
int num[2*N];
vector<int>yu[2*N];

int main(){
    int n;
    scanf("%d",&n);
    for(int i=1;i<=n;i++){
        scanf("%d",&p[i].v);
        p[i].a=i*2-1;
        p[i].b=i*2;
    }
    sort(p+1,p+1+n);
    int head=0,tail=n;
    for(int i=1;i<=n;i++){
        if (!mp[p[i].a]) {
            mp[p[i].a] = ++head;
            num[head] = p[i].a;
        }
        int l = mp[p[i].a];
        int r = l + p[i].v;
        if(!num[r]&&r==tail+1){//優先插入
            num[r]=p[i].b;
            tail++;
            continue;
        }
        r--;//掛的位置要減1
        if(r==tail+1)tail++;
        if (num[r]||r<=n) {
            yu[r].push_back(p[i].b);
        } else {
            num[r] = p[i].b;
        }
    }
    for(int i=1;i<tail;i++){
        printf("%d %d\n",num[i],num[i+1]);
    }
    for(int i=1;i<=tail;i++){
        for(int v:yu[i]){
            printf("%d %d\n",num[i],v);
        }
    }
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章