2019雅礼集训 D2T1 two [模拟,线段树]

题目描述:

样例:

input:
5 1
1 1 1
4 2 1 1
3

output:
Blue
3
Red
1 3
Blue
1 2
Red
2

数据范围:

标签:模拟,线段树


没错,你没有看错,这题标签就是模拟。

然而我还是不会做

首先很容易想到用dfs序判断一个点是否在另一个点的子树内。

然后写个\(n^2\)暴力就有60分了。

考虑用数据结构优化:

对于蓝树中的一条边(x,y),记u为两点在红树中dfs序较小的点,v为较大的点。

那么若\((x,y)\)\((a,b)(dfn[a]<dfn[b])\)有害,则有\(dfn[b]<=dfn[u]<=low[b],dfn[v]>low[b]\)\(dfn[b]<=dfn[v]<=low[b],dfn[u]<dfn[b]\)

用两棵线段树分别维护两种情况:

一棵以\(dfn[u]\)为下标,以\(dfn[v]\)单调递增的顺序在每一个线段树节点\([L,R]\)中排列。

一棵以\(dfn[v]\)为下标,以\(dfn[u]\)单调递减的顺序在每一个线段树节点\([L,R]\)中排列。

那么每次在一个节点中删点就相当于删除尾端的若干个元素。

分析一下就会发现这时间、空间复杂度都是\(O(nlogn)\)的。

口胡完了,代码够你写的,毕竟两种情况分别写真的很烦。我写了4kb。

所以说这是模拟嘛……

#include<bits/stdc++.h>
namespace my_std{
    using namespace std;
    #define mod 998244353
    #define pii pair<int,int>
    #define fir first
    #define sec second
    #define MP make_pair
    #define rep(i,x,y) for (int i=(x);i<=(y);i++)
    #define drep(i,x,y) for (int i=(x);i>=(y);i--)
    #define go(x) for (int i=head[T][x],v;(v=edge[T][i].t,i);i=edge[T][i].nxt)
    #define sz 200020
    typedef long long ll;
    template<typename T>
    inline void read(T& t)
    {
        t=0;char f=0,ch=getchar();
        double d=0.1;
        while(ch>'9'||ch<'0') f|=(ch=='-'),ch=getchar();
        while(ch<='9'&&ch>='0') t=t*10+ch-48,ch=getchar();
        if(ch=='.')
        {
            ch=getchar();
            while(ch<='9'&&ch>='0') t+=d*(ch^48),d*=0.1,ch=getchar();
        }
        t=(f?-t:t);
    }
    template<typename T,typename... Args>
    inline void read(T& t,Args&... args){read(t); read(args...);}
    void file()
    {
        #ifndef ONLINE_JUDGE
        freopen("a.txt","r",stdin);
        #endif
    }
    inline ll mul(ll a,ll b){ll d=(ll)(a*(double)b/mod+0.5);ll ret=a*b-d*mod;if (ret<0) ret+=mod;return ret;}
}
using namespace my_std;
int n,m;
int T;
struct hh{int t,nxt;}edge[2][sz<<1];
int head[2][sz],ecnt;
void make_edge(int f,int t)
{
    edge[T][++ecnt]=(hh){t,head[T][f]};
    head[T][f]=ecnt;
    edge[T][++ecnt]=(hh){f,head[T][t]};
    head[T][t]=ecnt;
}
int dfn[2][sz],low[2][sz],cnt;
void dfs(int x,int fa)
{
    dfn[T][x]=++cnt;
    go(x) if (v!=fa) dfs(v,x);
    low[T][x]=cnt;
}
int u[2][sz],v[2][sz],id[sz];
vector<int>t1[2][sz<<2],t2[2][sz<<2];
#define lson k<<1,l,mid
#define rson k<<1|1,mid+1,r
void ins1(int k,int l,int r,int x,int w)
{
    t1[T][k].push_back(w);
    if (l==r) return;
    int mid=(l+r)>>1;
    if (x<=mid) ins1(lson,x,w);
    else ins1(rson,x,w);
}
void ins2(int k,int l,int r,int x,int w)
{
    t2[T][k].push_back(w);
    if (l==r) return;
    int mid=(l+r)>>1;
    if (x<=mid) ins2(lson,x,w);
    else ins2(rson,x,w);
}
bool del[2][sz];
int tmp[sz],c,ans[sz],cc;
void query1(int k,int l,int r,int x,int y)
{
    if (x<=l&&r<=y)
    {
        while (t1[T][k].size())
        {
            int t=t1[T][k].back();
            if (dfn[T^1][u[T][t]]<x)
            {
                t1[T][k].pop_back();
                if (!del[T][t]) ans[++cc]=t,del[T][t]=1;
            }
            else break;
        }
        return;
    }
    int mid=(l+r)>>1;
    if (x<=mid) query1(lson,x,y);
    if (y>mid) query1(rson,x,y);
}
void query2(int k,int l,int r,int x,int y)
{
    if (x<=l&&r<=y)
    {
        while (t2[T][k].size())
        {
            int t=t2[T][k].back();
            if (dfn[T^1][v[T][t]]>y)
            {
                t2[T][k].pop_back();
                if (!del[T][t]) ans[++cc]=t,del[T][t]=1;
            }
            else break;
        }
        return;
    }
    int mid=(l+r)>>1;
    if (x<=mid) query2(lson,x,y);
    if (y>mid) query2(rson,x,y);
}
inline bool cmp1(const int &x,const int &y){return dfn[T^1][u[T][x]]>dfn[T^1][u[T][y]];}
inline bool cmp2(const int &x,const int &y){return dfn[T^1][v[T][x]]<dfn[T^1][v[T][y]];}
void IN()
{
    int x;
    rep(i,2,n) read(x),make_edge(x,i),u[T][i-1]=x,v[T][i-1]=i;
    dfs(1,0);
}
void init()
{
    rep(i,1,n-1) if (dfn[T^1][u[T][i]]>dfn[T^1][v[T][i]]) swap(u[T][i],v[T][i]);
    sort(id+1,id+n,cmp1);
    rep(i,1,n-1) ins1(1,1,n,dfn[T^1][v[T][id[i]]],id[i]);
    sort(id+1,id+n,cmp2);
    rep(i,1,n-1) ins2(1,1,n,dfn[T^1][u[T][id[i]]],id[i]);
}
int main()
{
    freopen("two.in","r",stdin);freopen("two.out","w",stdout);
    read(n);
    int x,y;
    T=0;ecnt=cnt=0;IN();T=1;ecnt=cnt=0;IN();
    rep(i,1,n-1) id[i]=i;
    T=0;init();T=1;init();
    T=0;
    read(tmp[c=1]);del[0][tmp[1]]=1;
    printf("Blue\n%d\n",tmp[1]);
    while (233)
    {
        cc=0;T^=1;
        rep(i,1,c)
        {
            x=u[T^1][tmp[i]],y=v[T^1][tmp[i]];
            if (dfn[T^1][x]<dfn[T^1][y]) swap(x,y);
            query1(1,1,n,dfn[T^1][x],low[T^1][x]);
            query2(1,1,n,dfn[T^1][x],low[T^1][x]);
        }
        if (!cc) return 0;
        puts(T?"Red":"Blue");
        sort(ans+1,ans+cc+1);
        rep(i,1,cc-1) printf("%d ",tmp[i]=ans[i]);
        printf("%d\n",tmp[cc]=ans[cc]);
        c=cc;
    }
}

猜你喜欢

转载自www.cnblogs.com/p-b-p-b/p/10234382.html
今日推荐