1. 程式人生 > >【CF429E】Points and Segments(歐拉回路)

【CF429E】Points and Segments(歐拉回路)

次數 sort ont 其他 pro problems get 但是 題解

【CF429E】Points and Segments(歐拉回路)

題面

CF
洛谷

題解

歐拉回路有這樣一個性質,如果把所有點在平面內排成一行,路徑看成區間的覆蓋,那麽每個點被從左往右的覆蓋次數等於從右往左的覆蓋次數。
發現這題很類似上面這個東西。
\(L\)\(R+1\)連邊,但是不能直接做歐拉回路,因為圖不連通。
找到度數為奇數的所有點,把相鄰的兩個兩兩配對,然後在他們之間連條邊,然後求解歐拉回路。
因為這樣子配對完之後新增的區間不交,令黑色區間為\(+1\),白色區間為\(-1\),那麽除了相鄰兩個奇度數點之間的區間外,其他區間的權值和為\(0\),而奇度數之間的區間的絕對值為\(1\)


那麽這個問題就解決完了。
還是註意即是這樣子連完了邊還可能不連通,所以每個連通塊都要跑一遍。

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
#define MAX 400100
inline int read()
{
    int x=0;bool t=false;char ch=getchar();
    while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
    if(ch=='-')t=true,ch=getchar();
    while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
    return t?-x:x;
}
int n,L[MAX],R[MAX];
int S[MAX],top;
struct Line{int v,next;}e[MAX];
int h[MAX],cnt=2,dg[MAX];
inline void Add(int u,int v){e[cnt]=(Line){v,h[u]};h[u]=cnt++;dg[v]+=1;}
int vis[MAX];bool book[MAX];
void dfs(int u)
{
    for(int &i=h[u];i;i=e[i].next)
    {
        int v=e[i].v,j=i;if(book[i>>1])continue;
        book[i>>1]=true;dfs(v);vis[j>>1]=u<v;
    }
}
int main()
{
    n=read();
    for(int i=1;i<=n;++i)L[i]=read(),R[i]=read();
    for(int i=1;i<=n;++i)S[++top]=L[i],S[++top]=L[i]-1;
    for(int i=1;i<=n;++i)S[++top]=R[i],S[++top]=R[i]+1;
    sort(&S[1],&S[top+1]);top=unique(&S[1],&S[top+1])-S-1;
    for(int i=1;i<=n;++i)L[i]=lower_bound(&S[1],&S[top+1],L[i])-S;
    for(int i=1;i<=n;++i)R[i]=lower_bound(&S[1],&S[top+1],R[i])-S;
    for(int i=1;i<=n;++i)Add(L[i],R[i]+1),Add(R[i]+1,L[i]);
    for(int i=1,lst=0;i<=top;++i)if(dg[i]&1)lst?Add(i,lst),Add(lst,i),lst=0:lst=i;
    for(int i=2;i<cnt;i+=2)if(!book[i>>1])dfs(e[i].v);
    for(int i=1;i<=n;++i)printf("%d ",vis[i]);
    return 0;
}

【CF429E】Points and Segments(歐拉回路)