BZOJ 3319 黑白树 并查集+线段树

Posted TS_Hugh

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了BZOJ 3319 黑白树 并查集+线段树相关的知识,希望对你有一定的参考价值。

这这这这这这什么毒瘤题!!!!!!!!!!!!!!!!!!!!!!!!!!!!

卡LCT(优秀的LCT由于是均摊本身就带着2,3的常数在,而且这道题对于LCT标记十分难维护,又得乘上4,5然后就炸了),卡树剖,卡正解,但是暴力能A!!!!!!!!!!!!!!!!!!!!!!

所谓正解就是线段树为护dfs序+并查集删点去重,这东西在每个点一秒的时候都过不了Po姐都虚。

但是我在网上看到一个大佬有一个神思路A掉了

下面是我改过之后的的TLE程序

#include<cstdio>
#include<cstring>
#include<ctime>
#include<iostream>
#include<cstdlib>
#define MAXN 1000010
using namespace std;
inline int read()
{
     int sum=0;
     char ch=getchar();
     while(ch<0||ch>9)ch=getchar();
     while(ch>=0&&ch<=9)
     {
         sum=(sum<<1)+(sum<<3)+ch-0;
         ch=getchar();
     }
     return sum;
}
struct Tr
{
    int to,next,id;
}c[MAXN<<1];
int head[MAXN],t;
int f[MAXN],fid[MAXN],id[MAXN],l[MAXN],r[MAXN],sz,deep[MAXN];
int fa[MAXN];
inline void add(int x,int y,int z)
{
    c[++t].to=y;
    c[t].next=head[x];
    head[x]=t;
    c[t].id=z;
}
void dfs(int x,int FA,int FID,int d)
{
    f[x]=FA;
    fid[x]=FID;
    id[x]=++sz;
    l[x]=sz;
    for(int i=head[x];i;i=c[i].next)
    if(c[i].to!=FA)
    {
      dfs(c[i].to,x,c[i].id,d+1)
      deep[c[i].id]=d+1;
    }
    r[x]=sz;
}
struct Seg_Tree
{
    struct Node
    {
        Node *ch[2];
        int l,r,mid,id;
        void pushdown()
        {
           ch[0]->id=deep[id]>deep[ch[0]->id]?id:ch[0]->id;
           ch[1]->id=deep[id]>deep[ch[1]->id]?id:ch[1]->id;
        }
    }node[MAXN<<2],*root;
    int sz,n;
    Node *New(int l,int r)
    {
        Node *x=&node[sz++];
        x->l=l;
        x->r=r;
        x->mid=(l+r)>>1;
        return x;
    }
    void build(Node *p)
    {
        if(p->l==p->r)return;
        p->ch[0]=New(p->l,p->mid);
        p->ch[1]=New(p->mid+1,p->r);
        build(p->ch[0]);
        build(p->ch[1]);
    }
    void Init()
    {
        root=New(1,n);
        build(root);
    }
    void update(Node *p,int l,int r,int id)
    {
       if(p->l>=l&&p->r<=r)
       {
           p->id=deep[id]>deep[p->id]?id:p->id;
           return;
       }
       p->pushdown();
       if(l<=p->mid)update(p->ch[0],l,r,id);
       if(p->mid<r)update(p->ch[1],l,r,id);
    }
    int query(Node *p,int pos)
    {
       if(p->l==p->r)return p->id;
       p->pushdown();
       return query(pos>p->mid?p->ch[1]:p->ch[0],pos);
    }
}YY;
inline int find(int x)
{
    return x==fa[x]?x:(fa[x]=find(fa[x]));
}
inline void unit(int x,int y)
{
     fa[find(x)]=find(y);
}
inline void gan(int x,int y)
{
    if(find(x)==find(y))return;
    if(deep[find(x)]<deep[find(y)])x^=y^=x^=y;
    while(deep[find(x)]>deep[find(y)])
    {
       int X=find(x);
       YY.update(YY.root,l[X],r[X],fid[X]);
       unit(X,f[X]);
    }
    while(find(x)!=find(y))
    {
        if(deep[find(x)]<deep[find(y)])x^=y^=x^=y;
        int X=find(x);
        YY.update(YY.root,l[X],r[X],fid[X]);
        unit(X,f[X]);
    }
}
int main()
{
    freopen("wbtree.in","r",stdin);
    freopen("wbtree.out","w",stdout);
    int n=YY.n=read();
    YY.Init();
    int T=read();
    for(int i=1;i<n;i++)
    {
        int x=read(),y=read();
        add(x,y,i);
        add(y,x,i);
    }
    dfs(1,0,0,0);
    for(int i=1;i<=n;i++)fa[i]=i;
    while(T--)
    {
        int opt=read(),x=read();
        if(opt==1)printf("%d\n",YY.query(YY.root,id[x]));
        else
        {
            int y=read();
            gan(x,y);
        }
    }
    return 0;
}

 

以上是关于BZOJ 3319 黑白树 并查集+线段树的主要内容,如果未能解决你的问题,请参考以下文章

BZOJ3319黑白树 并查集

bzoj2733 [ HNOI2012 ] -- 并查集+线段树合并

[BZOJ2733] [HNOI2012]永无乡(并查集 + 线段树合并)

BZOJ1453[Wc]Dface双面棋盘 线段树+并查集

bzoj2049 线段树 + 可撤销并查集

BZOJ 3319 黑白树