• LuoguP4271 [USACO18FEB]New Barns P 树的直径+LCT


    结论:如果边权非负,则距离树上一个点最远的点一定是直径端点之一.   

    由此可得我们只需维护树的直径就行.   

    这种维护方法的局限性在于不可以有删边操作.     

    假如合并两个连通块 A,B, 直径端点分别为 $x_{0},x_{1},x_{2},x_{3}$,新树直径的端点一定是在 4 个点中的两个.   

    那就两两取 max,然后求直径端点距离 x 的距离用 LCT 中的 split 就行了.   

    code: 

    #include <cstdio> 
    #include <algorithm>     
    #define N 100008      
    #define ls s[x].ch[0] 
    #define rs s[x].ch[1]   
    #define setIO(s) freopen(s".in","r",stdin) 
    using namespace std;  
    struct data {     
        int rev,f,ch[2],si; 
    }s[N];  
    int p[N],ax[N],bx[N],w[N],sta[N];            
    int get(int x) { return s[s[x].f].ch[1]==x; }   
    int isr(int x) { return s[s[x].f].ch[0]!=x&&s[s[x].f].ch[1]!=x; }
    void pushup(int x) { s[x].si=s[ls].si+s[rs].si+1; }
    void rotate(int x) { 
        int old=s[x].f,fold=s[old].f,which=get(x);  
        if(!isr(old))  
            s[fold].ch[s[fold].ch[1]==old]=x;   
        s[old].ch[which]=s[x].ch[which^1];  
        if(s[old].ch[which])  
            s[s[old].ch[which]].f=old;  
        s[x].ch[which^1]=old,s[old].f=x,s[x].f=fold;  
        pushup(old),pushup(x);  
    }    
    void mark(int x) {  
        swap(ls,rs),s[x].rev^=1; 
    }  
    void pushdown(int x) {  
        if(s[x].rev) { 
            if(ls) mark(ls); 
            if(rs) mark(rs); 
            s[x].rev=0; 
        }
    }
    void splay(int x) {  
        int v=0,u=x,fa;  
        for(sta[++v]=u;!isr(u);u=s[u].f) sta[++v]=s[u].f;  
        for(;v;--v) pushdown(sta[v]);  
        for(u=s[u].f;(fa=s[x].f)!=u;rotate(x))  
            if(s[fa].f!=u) rotate(get(fa)==get(x)?fa:x); 
    } 
    void access(int x) {  
        for(int y=0;x;y=x,x=s[x].f) 
            splay(x),rs=y,pushup(x);    
    }  
    void makert(int x) {  
        access(x),splay(x),mark(x);  
    }
    void link(int x,int y) {  
        makert(x),s[x].f=y;    
    }
    void init() {  
        for(int i=0;i<N;++i) {
            p[i]=i;   
            w[i]=0,ax[i]=bx[i]=i;    
        }
    }   
    int find(int x) {  
        return p[x]==x?x:p[x]=find(p[x]);  
    }    
    int Dis(int x,int y) {  
        makert(x),access(y),splay(y);  
        return s[y].si-1;     
    }           
    struct node {  
        int x,y;    
        node(int x=0,int y=0):x(x),y(y){}  
    }ma[10];     
    void merge(int x,int y) {      
        int oa=find(x),ob=find(y);                  
        ma[1]=node(ax[oa],Dis(ax[oa],x));   
        ma[2]=node(bx[oa],Dis(bx[oa],x));   
        ma[3]=node(ax[ob],Dis(ax[ob],y));  
        ma[4]=node(bx[ob],Dis(bx[ob],y));     
        int a=0,b=0,c=0;  
        for(int i=1;i<=2;++i) 
            for(int j=3;j<=4;++j)    
                if(ma[i].y+ma[j].y+1>c) c=ma[i].y+ma[j].y+1,a=i,b=j;  
        if(c<max(w[oa],w[ob])) {     
            if(w[ob]>w[oa]) p[oa]=ob;     
            else p[ob]=oa;   
        } 
        else {
            p[oa]=ob;    
            w[ob]=c; 
            ax[ob]=ma[a].x;  
            bx[ob]=ma[b].x;           
        }
        link(x,y);    
    }
    int main() {  
        // setIO("input");    
        init();  
        int q,x,y,z,n=0; 
        char op[10];  
        scanf("%d",&q);   
        for(int i=1;i<=q;++i) {  
            scanf("%s",op);  
            if(op[0]=='B') {  
                scanf("%d",&x);     
                s[++n].si=1; 
                if(x!=-1) merge(n,x);       
            }  
            if(op[0]=='Q') {            
                scanf("%d",&x),y=find(x);  
                int a=ax[y],b=bx[y];   
                printf("%d
    ",max(Dis(x,a),Dis(x,b)));      
            }               
        }
        return 0;
    }
    

      

  • 相关阅读:
    vs2013运行qt.exe文件提示错误“找不到Qt5Cored.dll”
    基于stm32f1的lora开发基础通信实验
    vs出现找不到dll,重新安装程序可能会解决此问题
    C&C++&opencv文件操作
    出现无法解析的符号xxx(vs2013)
    opencv目标跟踪检测(C)
    vs运行出错:error MSB8020或error LNK1104: 无法打开文件“opencv_calib3d248d.lib/opencv_contribxxxd.lib”
    vs串口读写dll封装C++#(免费源码分享)
    stm32定时器操作配置()
    pwm控制ili9341背光屏幕亮度(stm32f4)
  • 原文地址:https://www.cnblogs.com/guangheli/p/13277767.html
Copyright © 2020-2023  润新知