1. 程式人生 > 其它 >資料庫_檢視事務觸發器儲存過程

資料庫_檢視事務觸發器儲存過程

P4374 [USACO18OPEN]Disruption P

分析

還是蠻套路的,我們來總結一下這題的推理過程

首先考慮,從每一條邊去找哪一條邊是我們需要的最短的替換路。發現太麻煩了,則正難則反,我們從新加的每一條路去考慮

對於新加的邊,其能更新其兩個端點在樹中的路徑

依據此,我們的問題即轉化為了,如何快速的對樹中路徑中的可以替換的最小值進行更新

嗷,還有一個小問題,邊權化點權,可以在這裡看到操作方法P4114 Qtree1

不難想到利用線段樹+樹剖

問題就結束了,時間複雜度為\(O(nlog^2n)\)

但這依舊不是最優寫法,我們可以考慮並查集(最近碰到好幾道並查集的,滋,明天看看能不能全部理解一下,欠)

AC_code

#include<bits/stdc++.h>
using namespace std;
const int N = 5e4 + 10,INF = 0x3f3f3f3f;
struct Node
{
    int l,r,mi;
}tr[N<<2];
int h[N],e[N<<1],ne[N<<1],idx;
int sz[N],dep[N],fa[N],son[N];
int top[N],id[N],ts;
int n,m;

void add(int a,int b)
{
    e[idx] = b,ne[idx] = h[a],h[a] = idx++;
}

void dfs1(int u,int pa,int depth)
{
    sz[u] = 1,dep[u] = depth,fa[u] = pa;
    for(int i=h[u];~i;i=ne[i])
    {
        int j = e[i];
        if(j==pa) continue;
        dfs1(j,u,depth+1);
        if(sz[j]>sz[son[u]]) son[u] = j;
        sz[u] += sz[j];
    }
}

void dfs2(int u,int tp)
{
    top[u] = tp,id[u] = ++ts;
    if(!son[u]) return ;
    dfs2(son[u],tp);
    for(int i=h[u];~i;i=ne[i])
    {
        int j = e[i];
        if(j==fa[u]||j==son[u]) continue;
        dfs2(j,j);
    }
}

void pushdown(int u)
{
    auto &root = tr[u],&left = tr[u<<1],&right = tr[u<<1|1];
    if(root.mi!=INF)
    {
        left.mi = min(left.mi,root.mi);
        right.mi = min(right.mi,root.mi);
        root.mi = INF;
    }
}

void build(int u,int l,int r)
{
    tr[u] = {l,r,INF};
    if(l==r) return ;
    int mid = l + r >> 1;
    build(u<<1,l,mid),build(u<<1|1,mid+1,r);
}

void modify(int u,int l,int r,int k)
{
    if(l<=tr[u].l&&tr[u].r<=r) 
    {
        tr[u].mi = min(tr[u].mi,k);
        return ;
    }
    pushdown(u);
    int mid = tr[u].l + tr[u].r >> 1;
    if(l<=mid) modify(u<<1,l,r,k);
    if(r>mid) modify(u<<1|1,l,r,k);
}

int query(int u,int x)
{
    if(tr[u].l==tr[u].r) return tr[u].mi;
    pushdown(u);
    int mid = tr[u].l + tr[u].r >> 1;
    if(x<=mid) return query(u<<1,x);
    else return query(u<<1|1,x);
}

int main()
{
    scanf("%d%d",&n,&m);
    vector<pair<int,int>> edges;
    memset(h,-1,sizeof h);
    for(int i=0;i<n-1;i++)
    {
        int a,b;scanf("%d%d",&a,&b);
        edges.push_back({a,b});
        add(a,b),add(b,a);
    }
    dfs1(1,-1,1);
    dfs2(1,1);
    build(1,1,n);
    while(m--)
    {
        int a,b,c;
        scanf("%d%d%d",&a,&b,&c);
        while(top[a]!=top[b])
        {
            if(dep[top[a]]<dep[top[b]]) swap(a,b);
            modify(1,id[top[a]],id[a],c);
            a = fa[top[a]];
        }
        if(a!=b)
        {
            if(dep[a]<dep[b]) swap(a,b);
            modify(1,id[b]+1,id[a],c);
        }
    }
    for(auto edge:edges)
    {
        int a = edge.first,b = edge.second;
        if(dep[a]<dep[b]) swap(a,b);
        int res = query(1,id[a]);
        if(res==INF) puts("-1");
        else printf("%d\n",res);
    }
    return 0;
}