zoukankan      html  css  js  c++  java
  • 洛谷 P4319 变化的道路 解题报告

    P4319 变化的道路

    题目描述

    小 w 和小 c 在 H 国,近年来,随着 H 国的发展,H 国的道路也在不断变化着

    根据 H 国的道路法,H 国道路都有一个值 (w),表示如果小 w 和小 c 通过这条道路,那么他们的 (L) 值会减少 (w),但是如果小 w 和 小 c 在之前已经经过了这条路,那么他们的 L 值不会减少

    H 国有 (N) 个国家,最开始 H 国有 (N−1) 条道路,这 (N−1) 条道路刚好构成一棵树

    小 w 将和小 c 从 H 国的城市 1 出发,游览 H 国的所有城市,总共游览 32766 天,对于每一天,他们都希望游览结束后 L 值还是一个正数, 那么他们出发时 L 值至少为多少

    H 国的所有边都是无向边,没有一条道路连接相同的一个城市

    输入输出格式

    输入格式:

    输入第 1 行,一个整数(N)

    输入第 2 至第 (N) 行,每行三个正整数 (u, v, w),表示城市 (u) 与城市 (v) 有一条值为 (w) 道路

    输入第 (N+1) 行,一个整数 (M),表示 H 国有 (M) 条正在变化的道路

    输入第 (N+2) 行到第 (N+M+1) 行,每行 5 个整数 (u, v, w, l, r),表示城市 (u) 到城市 (v) 有一条值为 (w) 的道路, 这条道路存在于第 (l) 天到第 (r)

    输出格式:

    输出共 32766 行,第 (i) 行表示第 (i) 天游览的 (L) 值至少为多少

    说明

    对于所有数据 : (1leq Nleq 50000, 1leq lleq rleq rmleq 32766, 1leq wleq 10^9)


    线段树分治+LCT维护动态最小生成树,比较裸

    注意撤回的时候倒过来撤回,RE了一次


    Code:

    #include <cstdio>
    #include <algorithm>
    #include <vector>
    #define ll long long
    #define fa par[now]
    #define ls ch[now][0]
    #define rs ch[now][1]
    using std::max;
    const int N=2e5+10;
    const int M=32766;
    int ch[N][2],par[N],tag[N],s[N],tot,tmp,n,m;ll sum;
    struct node
    {
        int mx,id;
        bool friend operator <(node n1,node n2){return n1.mx<n2.mx;}
    }dat[N],mx[N];
    bool isroot(int now){return ch[fa][0]==now||ch[fa][1]==now;}
    int identity(int now){return ch[fa][1]==now;}
    void updata(int now){mx[now]=max(dat[now],max(mx[ls],mx[rs]));}
    void connect(int f,int now,int typ){ch[fa=f][typ]=now;}
    void Reverse(int now){tag[now]^=1,tmp=ls,ls=rs,rs=tmp;}
    void pushdown(int now)
    {
        if(tag[now])
        {
            if(ls) Reverse(ls);
            if(rs) Reverse(rs);
            tag[now]^=1;
        }
    }
    void Rotate(int now)
    {
        int p=fa,typ=identity(now);
        connect(p,ch[now][typ^1],typ);
        if(isroot(p)) connect(par[p],now,identity(p));
        else fa=par[p];
        connect(now,p,typ^1);
        updata(p),updata(now);
    }
    void splay(int now)
    {
        while(isroot(now)) s[++tot]=now,now=fa;s[++tot]=now;
        while(tot) pushdown(s[tot--]);now=s[1];
        for(;isroot(now);Rotate(now))
            if(isroot(fa))
                Rotate(identity(now)^identity(fa)?now:fa);
    }
    void access(int now)
    {
        for(int las=0;now;las=now,now=fa)
            splay(now),rs=las,updata(now);
    }
    void evert(int now){access(now),splay(now),Reverse(now);}
    void split(int u,int v){evert(u),access(v),splay(v);}
    void link(int u,int v){evert(u),par[u]=v;}
    void cat(int u,int v){split(u,v),ch[v][0]=par[u]=0,updata(v);}
    node query(int u,int v){split(u,v);return mx[v];}
    std::vector <int > seg[N];
    void Insert(int id,int L,int R,int l,int r,int p)
    {
        if(L==l&&R==r) {seg[id].push_back(p);return;}
        int Mid=L+R>>1;
        if(r<=Mid) Insert(id<<1,L,Mid,l,r,p);
        else if(l>Mid) Insert(id<<1|1,Mid+1,R,l,r,p);
        else Insert(id<<1,L,Mid,l,Mid,p),Insert(id<<1|1,Mid+1,R,Mid+1,r,p);
    }
    struct edge{int u,v,w;}Edge[N];
    void segdivide(int id,int l,int r)
    {
        std::vector <int > sav;
        for(int i=0;i<seg[id].size();i++)
        {
            int p=seg[id][i],las=0;
            int u=Edge[p].u,v=Edge[p].v,w=Edge[p].w;
            node tmp=query(u,v);
            if(tmp.mx>w)
            {
                sum=sum+w-tmp.mx;
                las=tmp.id;
                cat(Edge[las].u,las+n),cat(Edge[las].v,las+n);
                link(u,p+n),link(v,p+n);
            }
            sav.push_back(las);
        }
        int mid=l+r>>1;
        if(l==r)
            printf("%lld
    ",sum+1);
        else segdivide(id<<1,l,mid),segdivide(id<<1|1,mid+1,r);
        for(int las,p,i=seg[id].size()-1;~i;i--)
        {
            p=seg[id][i];
            if(las=sav[i])
            {
                int u=Edge[p].u,v=Edge[p].v;
                cat(u,p+n),cat(v,p+n);
                sum=sum+Edge[las].w-Edge[p].w;
                u=Edge[las].u,v=Edge[las].v;
                link(u,las+n),link(v,las+n);
            }
        }
    }
    int main()
    {
        scanf("%d",&n);
        for(int u,v,w,i=1;i<n;i++)
        {
            scanf("%d%d%d",&u,&v,&w);
            sum=sum+w;
            dat[i+n]=mx[i+n]={w,i};
            link(u,i+n),link(v,i+n);
            Edge[i]={u,v,w};
        }
        scanf("%d",&m);
        for(int u,v,w,l,r,i=0;i<m;i++)
        {
            scanf("%d%d%d%d%d",&u,&v,&w,&l,&r);
            Edge[i+n]={u,v,w};
            dat[i+(n<<1)]=mx[i+(n<<1)]={w,i+n};
            Insert(1,1,M,l,r,i+n);
        }
        segdivide(1,1,M);
        return 0;
    }
    

    2018.12.8

  • 相关阅读:
    mysql5.7 tar包安装
    jpa2.0以上findOne和getOne的区别
    终端设置代理
    virtualbox EFI安装Archlinux
    无法在web.xml或使用此应用程序部署的jar文件中解析绝对uri:[http://java.sun.com/jsp/jstl/core]
    代理模式笔记
    Mybatis详细的执行流程
    javaweb超市管理系统demo
    CF1409F Subsequences of Length Two
    1002: [FJOI2007]轮状病毒 基尔霍夫矩阵
  • 原文地址:https://www.cnblogs.com/butterflydew/p/10088244.html
Copyright © 2011-2022 走看看