1. 程式人生 > >【刷題】洛谷 P4319 變化的道路

【刷題】洛谷 P4319 變化的道路

tor line AR pty lse 輸入輸出格式 edge bool 之前

題目描述

小 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 值至少為多少

輸入輸出樣例

輸入樣例#1:

4
1 3 3
3 4 4
2 4 5
3
1 2 1 1 2
2 3 8 2 3
3 4 2 1 1

輸出樣例#1:

7
9
13
由於版面原因,僅顯示三行,接下來32763行都是13

說明

第一天,選擇 1 -(1)> 2 -(0)> 1 -(3)> 3 -(2)> 4,L 值總共減少了 6,所以 L 值至少為 7

第二天,選擇 1 -(1)> 2 -(0)> 1 -(3)> 3 -(4)> 4,L 值總共減少了 8,所以 L 值至少為 9

第三天及之後,選擇 1 -(3)> 3 -(4)> 4 -(5)> 2,L 值總共減少了 12,所以 L 值至少為 13

subtask1 : 15分,\(N = 100, rm = 233\)

subtask2 : 15分,\(N = 1000, rm = 2333\)

subtask3 : 20分,\(N = 49998, rm = 32766, l = r\)

subtask4:20分,\(N = 49999, rm = 32766, r = rm\)

subtask5:30分,\(N = 50000, rm = 32766\)

對於subtask3 : \(M = rm\) ,對於其他subtask:\(M=3\times rm\)

對於所有數據 : \(1\leq N\leq 50000, 1\leq l\leq r\leq rm\leq 32766, 1\leq w\leq 10^9\)

題解

又是一道LCT與其它數據結構結合的題目
肯定離線做,怎麽離線?
考慮線段樹,一條邊在 \(l\)\(r\) 中出現,就在線段樹中 \(l\)\(r\) 的區間加上這條邊
最後訪問線段樹的每個葉子節點,然後往下遞歸的時候如果區間上有邊的標記,就加邊;到葉子節點的時候,算答案;回溯的時候,把在這個區間內加的邊又刪去。(當然,這個線段樹雖然要打標記,但是不會有pushdown的)
然後就做完了

#include<bits/stdc++.h>
#define ui unsigned int
#define ll long long
#define db double
#define ld long double
#define ull unsigned long long
const int MAXN=200000+10,inf=0x3f3f3f3f;
int n,m,scnt;
ll ans;
struct edge{
    int u,v,w;
};
edge side[MAXN];
#define lc(x) ch[(x)][0]
#define rc(x) ch[(x)][1]
struct LCT{
    int ch[MAXN][2],fa[MAXN],rev[MAXN],stack[MAXN],cnt,Mx[MAXN],id[MAXN],val[MAXN];
    inline void init()
    {
        memset(Mx,-inf,sizeof(Mx));
        memset(val,-inf,sizeof(val));
    }
    inline bool nroot(int x)
    {
        return lc(fa[x])==x||rc(fa[x])==x;
    }
    inline void reverse(int x)
    {
        std::swap(lc(x),rc(x));
        rev[x]^=1;
    }
    inline void pushup(int x)
    {
        Mx[x]=val[x],id[x]=x;
        if(Mx[lc(x)]>Mx[x])Mx[x]=Mx[lc(x)],id[x]=id[lc(x)];
        if(Mx[rc(x)]>Mx[x])Mx[x]=Mx[rc(x)],id[x]=id[rc(x)];
    }
    inline void pushdown(int x)
    {
        if(rev[x])
        {
            if(lc(x))reverse(lc(x));
            if(rc(x))reverse(rc(x));
            rev[x]=0;
        }
    }
    inline void rotate(int x)
    {
        int f=fa[x],p=fa[f],c=(rc(f)==x);
        if(nroot(f))ch[p][rc(p)==f]=x;
        fa[ch[f][c]=ch[x][c^1]]=f;
        fa[ch[x][c^1]=f]=x;
        fa[x]=p;
        pushup(f);
        pushup(x);
    }
    inline void splay(int x)
    {
        cnt=0;
        stack[++cnt]=x;
        for(register int i=x;nroot(i);i=fa[i])stack[++cnt]=fa[i];
        while(cnt)pushdown(stack[cnt--]);
        for(register int y=fa[x];nroot(x);rotate(x),y=fa[x])
            if(nroot(y))rotate((lc(y)==x)==(lc(fa[y])==y)?y:x);
        pushup(x);
    }
    inline void access(int x)
    {
        for(register int y=0;x;x=fa[y=x])splay(x),rc(x)=y,pushup(x);
    }
    inline void makeroot(int x)
    {
        access(x);splay(x);reverse(x);
    }
    inline void split(int x,int y)
    {
        makeroot(x);access(y);splay(y);
    }
    inline void link(int x,int y)
    {
        makeroot(x);fa[x]=y;
    }
    inline void cut(int x,int y)
    {
        split(x,y);fa[x]=lc(y)=0;pushup(y);
    }
};
LCT T1;
#undef lc
#undef rc
template<typename T> inline void read(T &x)
{
    T data=0,w=1;
    char ch=0;
    while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
    if(ch=='-')w=-1,ch=getchar();
    while(ch>='0'&&ch<='9')data=((T)data<<3)+((T)data<<1)+(ch^'0'),ch=getchar();
    x=data*w;
}
template<typename T> inline void write(T x,char c='\0')
{
    if(x<0)putchar('-'),x=-x;
    if(x>9)write(x/10);
    putchar(x%10+'0');
    if(c!='\0')putchar(c);
}
template<typename T> inline void chkmin(T &x,T y){x=(y<x?y:x);}
template<typename T> inline void chkmax(T &x,T y){x=(y>x?y:x);}
template<typename T> inline T min(T x,T y){return x<y?x:y;}
template<typename T> inline T max(T x,T y){return x>y?x:y;}
#define Mid ((l+r)>>1)
#define lson rt<<1,l,Mid
#define rson rt<<1|1,Mid+1,r
struct SEG{
    std::vector<int> V[MAXN];
    inline void Update(int rt,int l,int r,int L,int R,int k)
    {
        if(L<=l&&r<=R)V[rt].push_back(k);
        else
        {
            if(L<=Mid)Update(lson,L,R,k);
            if(R>Mid)Update(rson,L,R,k);
        }
    }
    inline void Query(int rt,int l,int r)
    {
        std::stack< std::pair<int,int> > S;
        for(register int i=0,limit=V[rt].size();i<limit;++i)
        {
            int u=side[V[rt][i]].u,v=side[V[rt][i]].v,w=side[V[rt][i]].w,sn=V[rt][i]+n;
            T1.split(u,v);
            if(w<T1.Mx[v])
            {
                ans-=T1.Mx[v]-w;
                int so=T1.id[v];
                T1.cut(so,side[so-n].u);T1.cut(so,side[so-n].v);
                S.push(std::make_pair(so,1));
                T1.val[sn]=w;
                T1.link(sn,u);T1.link(sn,v);
                S.push(std::make_pair(sn,0));
            }
        }
        if(l==r)write(ans+1,'\n');
        else Query(lson),Query(rson);
        while(!S.empty())
        {
            std::pair<int,int> now=S.top();
            S.pop();
            int sn=now.first;
            if(!now.second)T1.cut(side[sn-n].u,sn),T1.cut(side[sn-n].v,sn),ans-=side[sn-n].w;
            else T1.link(side[sn-n].u,sn),T1.link(side[sn-n].v,sn),ans+=side[sn-n].w;
        }
    }
};
SEG T2;
#undef Mid
#undef lson
#undef rson
int main()
{
    read(n);
    for(register int i=1;i<n;++i)
    {
        int u,v,w,sn=i+n;
        read(u);read(v);read(w);
        side[++scnt]=(edge){u,v,w};
        ans+=w;
        T1.val[sn]=w;
        T1.link(sn,u);T1.link(sn,v);
    }
    read(m);
    for(register int i=1;i<=m;++i)
    {
        int u,v,w,l,r;
        read(u);read(v);read(w);read(l);read(r);
        side[++scnt]=(edge){u,v,w};
        T2.Update(1,1,32766,l,r,scnt);
    }
    T2.Query(1,1,32766);
    return 0;
}

【刷題】洛谷 P4319 變化的道路