【好题】线段树+贪心+思维——cf1248F

位置的嵌套把我弄晕了。。。总感觉多写了一层

/*
首先要找到一种满足条件的排列方式
给所有段按(左端点,右端点)升序排序,然后分配位置
    从左到右扫描位置i,把左端点<i的所有Seg放入优先队列 
    优先队列每次取出右端点最小的
     
然后考虑两个段是否可以交换顺序:设段[l,r]被分配的位置是x    
    那么和他交换的段位置只能在[l,x-1],[x+1,r]里找,只要找到[l,x-1]位置右端点最大值,[x+1,r]位置左端点最小值
    判能否越过x即可 
*/
#include<bits/stdc++.h>
using namespace std;
#define N 200005

int n;
struct Seg{
    int l,r,id;
    bool operator>(Seg a)const {
        return r>a.r;
    }
}s[N],ss[N];
int cmp(Seg a,Seg b){return a.l<b.l;}

priority_queue<Seg,vector<Seg>,greater<Seg> >pq; 
int ans1[N],ans2[N],tmp[N];

#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
int mx[N<<2],mi[N<<2];
void update1(int pos,int id,int l,int r,int rt){
    if(l==r){mx[rt]=id;return;}
    int m=l+r>>1;
    if(pos<=m)update1(pos,id,lson);
    else update1(pos,id,rson);
    
    if(!mx[rt<<1]){
        mx[rt]=mx[rt<<1|1];return;
    }
    if(!mx[rt<<1|1]){
        mx[rt]=mx[rt<<1];return;
    }
    int id1=mx[rt<<1],id2=mx[rt<<1|1];
    if(ss[id1].r>=ss[id2].r)mx[rt]=id1;
    else mx[rt]=id2; 
}
int query1(int L,int R,int l,int r,int rt){
    if(L>R)return 0;
    if(L<=l && R>=r)return mx[rt];
    int m=l+r>>1,res=0;
    if(L<=m)res=query1(L,R,lson);
    if(R>m){
        if(!res)res=query1(L,R,rson);
        else {
            int res2=query1(L,R,rson);
            if(ss[res].r<ss[res2].r)res=res2;
        }
    }
    return res;
}

void update2(int pos,int id,int l,int r,int rt){
    if(l==r){mi[rt]=id;return;}
    int m=l+r>>1;
    if(pos<=m)update2(pos,id,lson);
    else update2(pos,id,rson);
    
    if(!mi[rt<<1]){
        mi[rt]=mi[rt<<1|1];return;
    }
    if(!mi[rt<<1|1]){
        mi[rt]=mi[rt<<1];return;
    }
    int id1=mi[rt<<1],id2=mi[rt<<1|1];
    if(ss[id1].l<=ss[id2].l)mi[rt]=id1;
    else mi[rt]=id2; 
}
int query2(int L,int R,int l,int r,int rt){
    if(L>R)return 0;
    if(L<=l && R>=r)return mi[rt];
    int m=l+r>>1,res=0;
    if(L<=m)res=query2(L,R,lson);
    if(R>m){
        if(!res)res=query2(L,R,rson);
        else {
            int res2=query2(L,R,rson);
            if(ss[res].l>ss[res2].l)res=res2;
        }
    }
    return res;
}
int pos[N];
int main(){
    cin>>n;
    for(int i=1;i<=n;i++){
        cin>>s[i].l>>s[i].r;
        s[i].id=i;
    }
    memcpy(ss,s,sizeof s);
    sort(s+1,s+1+n,cmp);
    
    int p=1;
    for(int i=1;i<=n;i++){
        while(p<=n && s[p].l<=i){
            pq.push(s[p]);
            ++p;
        }
        Seg now=pq.top();pq.pop();
        ans1[i]=now.id;
    }
    //for(int i=1;i<=n;i++)pos[ans[i].id]=i;

    for(int i=1;i<=n;i++){
        update1(i,ans1[i],1,n,1);
        update2(i,ans1[i],1,n,1);
    }    
    int flag=0,p1,p2;
    memcpy(ans2,ans1,sizeof ans1);
    for(int i=1;i<=n;i++){
        int L1=ss[ans1[i]].l,R1=i-1;
        int L2=i+1,R2=ss[ans1[i]].r;
        int res1=query1(L1,R1,1,n,1);
        int res2=query2(L2,R2,1,n,1);
        if(res1 && ss[res1].r>=i){
            flag=1;
            p1=ans1[i],p2=res1;
            break;    
        }
        if(res2 && ss[res2].l<=i){
            flag=1;
            p1=ans1[i],p2=res2;
            break;
        }
    }
    if(flag){
        puts("NO");
        for(int i=1;i<=n;i++)
            tmp[ans1[i]]=i;
        for(int i=1;i<=n;i++)cout<<tmp[i]<<" ";
        puts("");
        swap(tmp[p1],tmp[p2]);//1 4 2 3
        for(int i=1;i<=n;i++)cout<<tmp[i]<<" ";
        puts("");
    }else {
        puts("YES");
            for(int i=1;i<=n;i++)
            tmp[ans1[i]]=i;
        for(int i=1;i<=n;i++)cout<<tmp[i]<<" ";
        puts("");
    }
} 

猜你喜欢

转载自www.cnblogs.com/zsben991126/p/12891909.html