zoukankan      html  css  js  c++  java
  • P2387 [NOI2014]魔法森林

    和最小差值生成树差不多

    都是用lct维护生成树的题目

    本题可以以a排序,再维护b(通常这种二维变量的题都差不多这样,先排序一维)

    然后我tm竟然rotate手误打错了一点...调了好久..

    然后关于pushup:关于最大值,最小值一类的信息要在pushup中赋初值,而异或和之类的可以不用

    就是说不可以用引用中写法的来写..

    #include<bits/stdc++.h>
    using namespace std;
    const int N=5e4+7;
    const int M=1e5+7;
    int n,m,st[N+M],tot,ans=1<<30,w[N+M];
    struct edge{
        int a,b,u,v;
        bool operator <(const edge &x)const {
            return a<x.a;
        }
    }e[M];
    struct tree{
        int ch[2],fa,mx=-1,id=-1;
        bool rev;
    }t[N+M];
    void pushup(int x) {
        t[x].mx=w[x],t[x].id=x;
        if(t[x].ch[0]&&t[t[x].ch[0]].mx>t[x].mx) t[x].mx=t[t[x].ch[0]].mx,t[x].id=t[t[x].ch[0]].id;
        if(t[x].ch[1]&&t[t[x].ch[1]].mx>t[x].mx) t[x].mx=t[t[x].ch[1]].mx,t[x].id=t[t[x].ch[1]].id;
    }
    void rev(int x){
        swap(t[x].ch[0],t[x].ch[1]);
        t[x].rev^=1;
    }
    void pushdown(int x){
        if(t[x].rev){
            if(t[x].ch[0])rev(t[x].ch[0]);
            if(t[x].ch[1])rev(t[x].ch[1]);
            t[x].rev=0;
        }
    }
    bool nroot(int x){
        return (t[t[x].fa].ch[0]==x)||(t[t[x].fa].ch[1]==x);
    }
    void rotate(int x){
        int y=t[x].fa;
        int z=t[y].fa;
        bool k=t[y].ch[1]==x;
        if(nroot(y))t[z].ch[t[z].ch[1]==y]=x;
        t[x].fa=z;
        t[y].ch[k]=t[x].ch[k^1];
        t[t[x].ch[k^1]].fa=y;
        t[x].ch[k^1]=y;
        t[y].fa=x;
        pushup(y);
        pushup(x);
    }
    void splay(int x){
        int y=0,z=x;
        st[++y]=z;
        while(nroot(z))st[++y]=z=t[z].fa;
        while(y)pushdown(st[y--]);
        while(nroot(x)){
            y=t[x].fa;
            z=t[y].fa;
            if(nroot(y))
                (t[y].ch[1]==x)^(t[z].ch[1]==y)?rotate(x):rotate(y);
            rotate(x);
        }
    }
    void access(int x){
        for(int y=0;x;y=x,x=t[x].fa){
            splay(x);
            t[x].ch[1]=y;
            pushup(x);
        }
    }
    void makeroot(int x){
        access(x);
        splay(x);
        rev(x);
    }
    void split(int x,int y){
        makeroot(x);
        access(y);
        splay(y);
    }
    int findroot(int x){
        access(x);
        splay(x);
        while(t[x].ch[0])x=t[x].ch[0];
        splay(x);
        return x;
    }
    void link(int x,int y){
        splay(x);
        t[x].fa=y;
    }
    bool check(int x,int y){
        makeroot(x);
        return findroot(y)==x;
    }
    int main(){
        cin>>n>>m;
        for(int i=1;i<=m;i++){
            scanf("%d%d%d%d",&e[i].u,&e[i].v,&e[i].a,&e[i].b);
        }
        sort(e+1,e+1+m);
        for(int i=1;i<=m;i++){
            int u=e[i].u;
            int v=e[i].v;
            //t[i+n].mx=e[i].b,t[i+n].id=i+n;
            w[i+n]=e[i].b;
            if(u==v)continue;
            if(!check(u,v)){
                link(u,i+n),link(i+n,v);
            }
            else {
                split(u,v);
                int now=t[v].id,maxx=t[v].mx;
                if(e[i].b>maxx)continue;
                splay(now),t[t[now].ch[0]].fa=t[t[now].ch[1]].fa=0;
                link(u,i+n),link(i+n,v);
            }
            if(check(1,n)){
                split(1,n);
                ans=min(ans,t[n].mx+e[i].a);
            }
        }
        if(ans==1<<30)puts("-1");
        else printf("%d
    ",ans);
        return 0;
    }
  • 相关阅读:
    hdu-4638
    一个简单的询问
    CoderForces-617B
    HYSBZ-2002弹飞绵羊
    邻接表
    CoderForces-913-C
    CoderForces-913D
    CoderFocers-620C
    CoderForces-375D
    HDU-6119
  • 原文地址:https://www.cnblogs.com/Hikigaya/p/10839767.html
Copyright © 2011-2022 走看看