zoukankan      html  css  js  c++  java
  • BZOJ 3319 黑白树 并查集+线段树

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

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

    考试的时候我撸了一发LCT可是.....我忘了rev标记的延迟性会影响到题中所需标记.......我们只有在spaly的时候才会用到pushdown是为了让传上去的东西·真,因为这个pushdown在把信息全部传下去之后也是会真的,但是我们不肯能一个一个下传再把它pushup上去,所以我们要传上去的是真的。因为我们用了标记因此影响他的只有他父亲,这时候我们需要在spaly的时候pushdown,然而这个时候我们等于把123456789 pushdown(fa)之后是678951234 再pushdown(x)之后是678953412,这就是在把x旋到fa的时候只是带着一个标记仍然是 6 9 端点而不是9 6,这就是说如果只是把那个pushdown主体弄成了真的但是他的儿子确实假的,所以我们旋转的时候pushup出来的也是假的!!!

    所谓正解就是线段树为护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
    ",YY.query(YY.root,id[x]));
            else
            {
                int y=read();
                gan(x,y);
            }
        }
        return 0;
    }
  • 相关阅读:
    判断DataSet为空
    msxml3.dll 错误 '800c0008'
    google Map api地理位置坐标转换
    C# .net中cookie值为中文时的乱码解决方法
    windows pear 安装
    smarty2 设置、变量、函数
    简单模板类
    mysql 1366 插入错误
    Oracle修改账户口令
    C# Winform验证码
  • 原文地址:https://www.cnblogs.com/TSHugh/p/7172178.html
Copyright © 2011-2022 走看看