圆方树

oiwiki

P4630 [APIO2018] 铁人两项

#include <bits/stdc++.h>
using namespace std;
const int N = 400005;
typedef long long ll;
ll ans = 0;
int n, m,  dfn[N], low[N], tot = 0, val[N], cnt = 0, stk[N], hh = 0, siz[N], sbn;
vector<int> g[N], t[N];
void tarjan(int x)
{
    dfn[x] = low[x] = ++ tot;
    stk[++ hh] = x;
    val[x] = -1;
    sbn ++;
    for (int i = 0; i < g[x].size(); ++ i)
    {
        int y =  g[x][i];
        if(!dfn[y])
        {
            tarjan(y);
            low[x] = min(low[x], low[y]);
            if(low[y] >= dfn[x])
            {
                cnt ++;
                int v = 0;
                do
                {
                   v = stk[hh --];
                   t[cnt].push_back(v);
                   t[v].push_back(cnt);
                } while (v != y);
                t[cnt].push_back(x);
                t[x].push_back(cnt);
                val[cnt] = t[cnt].size();
            }
        }
        else low[x] = min(low[x], dfn[y]);
    }
    return ;
}
void dfs(int x, int fa)
{
    if(x <= n) siz[x] = 1;
    for (int i = 0; i < t[x].size(); ++ i)
    {
        int y = t[x][i];
        if(y == fa) continue;
        dfs(y, x);
        ans = ans + (ll)val[x] * siz[x] * siz[y] * 2;
        siz[x] += siz[y];
    }
    ans = ans + (ll)siz[x] * (sbn - siz[x]) * val[x] * 2;
}
int main()
{
    scanf("%d %d", &n, &m);
    cnt = n;
    for (int i = 1; i <= m; ++ i)
    {
        int u, v;
        scanf("%d %d", &u, &v);
        g[u].push_back(v);
        g[v].push_back(u);
    }
    
    for (int i = 1; i <= n; ++ i)
    {
        if(!dfn[i]) tarjan(i), hh --, dfs(i, 0), sbn = 0;
    }
    printf("%lld", ans);

    return 0;
}

Tourists

#include <bits/stdc++.h>
using namespace std;
const int N = 200005;
const int inf = 2000000000;
int n, m, q, tot = 0, cnt = 0, hh = 0, resg = -1, rest = -1, stk[N], dfn[N], low[N], val[N];
int top[N], dep[N], fa[N], son[N], fdfn[N], mn[N << 2];
multiset<int> ss[N];
int read()
{
    int x = 0;
    char c = getchar();
    while(c < '0' || c > '9') c = getchar();
    while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
    return x;
}
struct edge
{
    int to, nxt;
}t[1000005], g[1000005];
int headt[N], headg[N];
void add_edget(int u, int v)
{
   t[++ rest].to = v, t[rest].nxt = headt[u], headt[u] = rest;
   return ;
}
void add_edgeg(int u, int v)
{
    g[++ resg].to = v, g[resg].nxt = headg[u], headg[u] = resg;
}
void tarjan(int x)
{
    dfn[x] = low[x] = ++ tot;
    stk[++ hh] = x;
    for (int i = headg[x]; i != -1; i = g[i].nxt)
    {
        int y = g[i].to;
        if(!dfn[y])
 
        {
            tarjan(y);
            low[x] = min(low[x], low[y]);
            if(low[y] >= dfn[x])
            {
                int v = 0;
                cnt ++;
                do
                {
                    v = stk[hh --];
                    add_edget(cnt, v);
                    add_edget(v, cnt);
                }while(v != y);
                add_edget(cnt, x);
                add_edget(x, cnt);
            }
        }
        else low[x] = min(low[x], dfn[y]);
    }
    return ;
}
int dfs1(int x, int fa)
{
    int siz = 1;
    int  maxsiz = 0;
    for (int i = headt[x]; i != -1; i = t[i].nxt)
    {
        int y = t[i].to;
        if(y == fa) continue;
        int s = dfs1(y, x);
        siz += s;
        if(s > maxsiz) maxsiz = s, son[x] = y;
    }    
    return siz;
}
void dfs2(int x, int v)
{
    top[x] = v, dep[x] = dep[fa[x]] + 1, dfn[x] = ++ tot, fdfn[tot] = x;
    if(son[x] <= n) ss[x].insert(val[son[x]]);
    if(son[x]) fa[son[x]] = x, dfs2(son[x], v);
    for (int i = headt[x]; i != -1; i = t[i].nxt)
    {
        int y = t[i].to;
        if(dfn[y]) continue;
        if(y <= n) ss[x].insert(val[y]);
        fa[y] = x;
        dfs2(y, y);
    }
    return ;
}
void build_tree(int p, int l, int r)
{
    if(l == r) 
    {
        if(fdfn[l] <= n) mn[p] = val[fdfn[l]];
        else 
        {
            auto it = ss[fdfn[l]].begin();
            mn[p] = *it;
        }
        return ;
    }
    int mid = l + r >> 1;
    build_tree(p << 1, l, mid);
    build_tree(p << 1 | 1, mid + 1, r);
    mn[p] = min(mn[p << 1], mn[p << 1 | 1]);
    return ;
}
void update(int p, int l, int r, int x, int k)
{
    if(l == r) 
    {
        mn[p] = k;
        return ;
    }
    int mid = l + r >> 1;
    if(x <= mid) update(p << 1, l, mid, x, k);
    else update(p << 1 | 1, mid + 1, r, x, k);
    mn[p] = min(mn[p << 1], mn[p << 1 | 1]);
    return ;
}
int query(int p, int l, int r, int L, int R)
{
    if(L <= l && r <= R) return mn[p];
    if(l > R || r < L) return inf;
    int mid = l + r >> 1;
    return min(query(p << 1, l, mid, L, R), query(p << 1 | 1, mid + 1, r, L, R));    
}
int get_path(int a, int b)
{
    int ans = inf;
    while(top[a] != top[b])
    {
        if(dep[top[a]] < dep[top[b]]) swap(a, b);
        ans = min(ans, query(1, 1, cnt, dfn[top[a]], dfn[a]));
        a = fa[top[a]];
    }
    if(dep[a] > dep[b]) swap(a, b);
    ans = min(ans, query(1, 1, cnt, dfn[a], dfn[b]));
    if(a > n) ans = min(ans, val[fa[a]]);
    return ans; 
}
int main()
{
    memset(headt, -1, sizeof headt);
    memset(headg, -1, sizeof headg);
    n = read(), m = read(), q = read();
    cnt = n;
    for (int i = 1; i <= n; ++ i) val[i] = inf;
    for (int i = 1; i <= n; ++ i) val[i] = read();
    for (int i = 1; i <= m; ++ i)
    {
        int u, v;
        scanf("%d %d", &u, &v);
        add_edgeg(u, v), add_edgeg(v, u);
    }
   
    tarjan(1);
   
    tot = 0;
    for (int i = 1; i <= n + n; ++ i) dfn[i] = 0;
    
    dfs1(1, 0);
 
    dfs2(1, 1);
   
    build_tree(1, 1, cnt);
 
    while(q --)
    {
        char s[3];
        scanf("%s", s + 1);
        if(s[1] == 'C')
        {
            int a, w;
            a = read(), w = read();
            if(a > 1 && a <= n)
            {
                int y = fa[a];
                auto it = ss[y].lower_bound(val[a]);
                ss[y].erase(it);
                ss[y].insert(w);
                it = ss[y].begin();
                update(1, 1, cnt, dfn[y], *it);    
            }
            update(1, 1, cnt, dfn[a], w);
            val[a] = w;
        }
        else
        {
            int a, b;
            a = read(), b = read();
            printf("%d\n", get_path(a, b));
        }
    }
    return 0;
}

posted @   Helioca  阅读(4)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!
Document
点击右上角即可分享
微信分享提示