zoukankan      html  css  js  c++  java
  • [构造] Codeforces 1278E Tests for problem D

    题目大意

    给定一棵(N(Nleq 5 imes 10^5))个点的树,每个点代表着一个线段,所有线段都不存在公共端点,且端点在([1,2 imes N])范围内。只有当两条线段相交但不内含时,这两条线段代表的点才会相连。要求求出这(N)个点所代表的线段的任意一种情况。

    题解

    我们去维护一个链表,开始时指定1号结点为根结点,并把1号结点的所代表的线段的两个端点插入链表。然后从1号结点进行DFS。每遍历到一个结点,就把它所代表的线段的左端点插入它父亲所代表的线段的右端点的左边,再把它所代表的线段的右端点插入它父亲所代表的线段的右端点的右边。最后遍历整个链表,给每个端点分配一个下标即可。时间复杂度(O(N))

    Code

    #include <iostream>
    #include <algorithm>
    #include <cstring>
    #include <cstdio>
    using namespace std;
    
    #define RG register int
    #define LL long long
    
    template<typename elemType>
    inline void Read(elemType &T){
        elemType X=0,w=0; char ch=0;
        while(!isdigit(ch)) {w|=ch=='-';ch=getchar();}
        while(isdigit(ch)) X=(X<<3)+(X<<1)+(ch^48),ch=getchar();
        T=(w?-X:X);
    }
    
    struct Node{int L,R;};
    Node LinkList[1000010];
    Node Ans[500010];
    struct edge{int Next,to;};
    edge G[1000010];
    int head[500010];
    int N,cnt=2,Index=0;
    
    inline void Add_Edge(int u,int v){
        G[cnt].to=v;
        G[cnt].Next=head[u];
        head[u]=cnt++;
    }
    
    inline void Maintain(int u,int fa){
        int B=LinkList[fa<<1|1].L;
        LinkList[B].R=u<<1;
        LinkList[u<<1].L=B;
        LinkList[fa<<1|1].L=u<<1;
        LinkList[u<<1].R=fa<<1|1;
        B=LinkList[fa<<1|1].R;
        LinkList[B].L=u<<1|1;
        LinkList[u<<1|1].R=B;
        LinkList[fa<<1|1].R=u<<1|1;
        LinkList[u<<1|1].L=fa<<1|1;
        return;
    }
    
    void DFS(int u,int fa){
        if(fa!=0) Maintain(u,fa);
        for(int i=head[u];i;i=G[i].Next){
            int v=G[i].to;
            if(v==fa) continue;
            DFS(v,u);
        }
        return;
    }
    
    void Solve(int u){
        while(LinkList[u].R!=0){
            ++Index;
            if(u&1) Ans[u>>1].R=Index;
            else Ans[u>>1].L=Index;
            u=LinkList[u].R;
        }
        ++Index;
        if(u&1) Ans[u>>1].R=Index;
        else Ans[u>>1].L=Index;
        return;
    }
    
    int main(){
        Read(N);
        for(RG i=1;i<=N-1;++i){
            int u,v;
            Read(u);Read(v);
            Add_Edge(u,v);
            Add_Edge(v,u);
        }
        LinkList[1<<1].R=1<<1|1;
        LinkList[1<<1|1].L=1<<1;
        DFS(1,0);
        int St=0;
        for(RG i=2;i<=(N<<1|1);++i)
            if(LinkList[i].L==0){St=i;break;}
        Solve(St);
        for(RG i=1;i<=N;++i)
            printf("%d %d
    ",Ans[i].L,Ans[i].R);
    
        return 0;
    }
    
  • 相关阅读:
    HashMap
    Spring事务异常回滚,捕获异常不抛出就不会回滚(转载) 解决了我一年前的问题
    脏读 不可重复读 幻读
    冒泡优化
    Class.forName的作用以及为什么要用它【转】
    java反射入门
    Java异常分类 转载
    转载 【CSS进阶】伪元素的妙用--单标签之美
    转载文章 利用旋转正方形与图形的组合实现爱心
    Three.js基础学习【修改版】
  • 原文地址:https://www.cnblogs.com/AEMShana/p/12386160.html
Copyright © 2011-2022 走看看