关闭

CodeForces 487E UOJ 30 Tourists Tarjan + 树链剖分

标签: codeforces线段树Tarjan双连通分量
818人阅读 评论(0) 收藏 举报
分类:

施工中。。。


以下代码需要C++11才可编译。。

#include <cstdio>
#include <algorithm>
#include <functional>
#include <set>
#include <cstring>
using namespace std;
#define FOR(i,j,k) for(i=j;i<=k;i++)
int read() {
    int s = 0, f = 1; char ch = getchar();
    for (; '0' > ch || ch > '9'; ch = getchar()) if (ch == '-') f = -1;
    for (; '0' <= ch && ch <= '9'; ch = getchar()) s = s * 10 + ch - '0';
    return s * f;
}

const int N = 100001, M = 2 * N;

struct Graph {
    int head[N], next[M], to[M], cnt;
    Graph() : cnt(0) {}
    void add(int u, int v) {
        next[++cnt] = head[u]; head[u] = cnt; to[cnt] = v;
        next[++cnt] = head[v]; head[v] = cnt; to[cnt] = u;
    }
};

struct BCC : Graph {
    int dfn[N], low[N], id[N], belong[N], cut[N], cnt;
    multiset<int> val[M];

    BCC() {
        cnt = 0;
    }

    function<void(int,int)> found_cut_point;
    
    void tarjan(int u) {
        static int ts = 0, top = 0;
        static int stack[N];
        int x, i;
        dfn[u] = low[u] = ++ts;
        stack[++top] = u;
        for (i = head[u]; i; i = next[i])
            if (!dfn[to[i]]) {
                tarjan(to[i]);
                low[u] = min(low[u], low[to[i]]);
                if (dfn[u] == low[to[i]]) {
                    cnt ++;
                    cut[u] = 1;
                    do {
                        x = stack[top--];
                        id[x] = cnt;
                        if (cut[x])
                            found_cut_point(x, cnt);
                    } while(x != to[i]);
                    found_cut_point(u, cnt);
                }
            } else low[u] = min(low[u], dfn[to[i]]);
    }
} bcc;

struct SegmentTree {
    int initial[M], mi[M];
    
    int build(int t, int l, int r) {
        if (l == r) return mi[t] = initial[l];
        int mid = l + r >> 1;
        return mi[t] = min(build(t * 2, l, mid), build(t * 2 + 1, mid + 1, r));
    }
    
    int query(int t, int l, int r, int ql, int qr) {
        if (l == ql && r == qr) return mi[t];
        int mid = l + r >> 1;
        if (qr <= mid) return query(t * 2, l, mid, ql, qr);
        else if (ql > mid) return query(t * 2 + 1, mid + 1, r, ql, qr);
        else return min(query(t * 2, l, mid, ql, mid),
            query(t * 2 + 1, mid + 1, r, mid + 1, qr));
    }
    
    void modify(int t, int l, int r, int x, int v) {
        if (l == r) { mi[t] = v; return; } 
        int mid = l + r >> 1;
        if (x <= mid) modify(t * 2, l, mid, x, v);
        else modify(t * 2 + 1, mid + 1, r, x, v);
        mi[t] = min(mi[t * 2], mi[t * 2 + 1]);
    }
} seg;

struct Tree : Graph {
    int son[N], sz[N], top[N], dep[N], pos[N], fa[N], id;
    SegmentTree *st;

    Tree() {
        id = 0;
    }
    
    void dfs1(int x) {
        son[x] = 0; sz[x] = 1;
        for (int i = head[x]; i; i = next[i])
            if (to[i] != fa[x]) {
                fa[to[i]] = x; dep[to[i]] = dep[x] + 1;
                dfs1(to[i]);
                sz[x] += sz[to[i]];
                if (sz[to[i]] > sz[son[x]]) son[x] = to[i];
            }
    }
    
    void dfs2(int x, int t) {
        top[x] = t; pos[x] = ++id;
        if (son[x]) dfs2(son[x], t);
        for (int i = head[x]; i; i = next[i])
            if (to[i] != fa[x] && to[i] != son[x])
                dfs2(to[i], to[i]);
    }
    
    int lca(int x, int y) {
        int fx = top[x], fy = top[y];
        while (fx != fy) {
            if (dep[fx] < dep[fy]) swap(fx, fy), swap(x, y);
            x = fa[fx], fx = top[x];
        }
        if (dep[x] > dep[y]) swap(x, y);
        return x;
    }
    
    int query(int x, int y) {
        int fx = top[x], fy = top[y], ans = 2147483647;
        while (fx != fy) {
            if (dep[fx] < dep[fy]) swap(fx, fy), swap(x, y);
            ans = min(ans, st->query(1, 1, id, pos[fx], pos[x]));
            x = fa[fx], fx = top[x];
        }
        if (dep[x] > dep[y]) swap(x, y);
        return min(ans, st->query(1, 1, id, pos[x], pos[y]));
    }
} tree;

int main() {
    static int w[N];
    char ch[2];
    int n = read(), m = read(), q = read(), i, x, y;
    FOR (i, 1, n) w[i] = read();
    tree.st = &seg;
    bcc.found_cut_point = [n] (int id, int bcc) {
        tree.add(id + n, bcc);
    };
    while (m--) bcc.add(read(), read());
    bcc.tarjan(1);
    FOR (i, 1, n) {
        if (i != 1)
            bcc.val[bcc.id[i]].insert(w[i]);
        if (bcc.cut[i])
            bcc.val[n + i].insert(2147483647);
    }
    tree.dfs1(n+1); tree.dfs2(n+1, n+1);
    memset(seg.initial, 127, sizeof seg.initial);
    FOR (i, 1, 2*n) if(tree.pos[i]) seg.initial[tree.pos[i]] = *bcc.val[i].begin();
    seg.build(1, 1, tree.id);
    while (q--) {
        scanf("%s%d%d", ch, &x, &y);
        if (ch[0] == 'C') {
            if (x != 1) {
                bcc.val[bcc.id[x]].erase(bcc.val[bcc.id[x]].find(w[x]));
                bcc.val[bcc.id[x]].insert(y);
                seg.modify(1, 1, tree.id, tree.pos[bcc.id[x]], *bcc.val[bcc.id[x]].begin());
            }
            w[x] = y;
        } else {
            if (x == y) printf("%d\n", w[x]);
            else {
                x=bcc.cut[x] ? x + n : bcc.id[x];  
                y=bcc.cut[y] ? y + n : bcc.id[y];
                int l = tree.lca(x, y);
                if (l <= bcc.cnt) l = tree.fa[l];
                printf("%d\n", min(w[l - n], tree.query(x, y));
            }
        }
    }
    return 0;
}


E. Tourists
time limit per test
2 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output

There are n cities in Cyberland, numbered from 1 to n, connected by m bidirectional roads. The j-th road connects city ajand bj.

For tourists, souvenirs are sold in every city of Cyberland. In particular, city i sell it at a price of wi.

Now there are q queries for you to handle. There are two types of queries:

  • "a w": The price in city a is changed to w.
  • "a b": Now a tourist will travel from city a to b. He will choose a route, he also doesn't want to visit a city twice. He will buy souvenirs at the city where the souvenirs are the cheapest (possibly exactly at city a or b). You should output the minimum possible price that he can buy the souvenirs during his travel.

More formally, we can define routes as follow:

  • A route is a sequence of cities [x1, x2, ..., xk], where k is a certain positive integer.
  • For any 1 ≤ i < j ≤ k, xi ≠ xj.
  • For any 1 ≤ i < k, there is a road connecting xi and xi + 1.
  • The minimum price of the route is min(wx1, wx2, ..., wxk).
  • The required answer is the minimum value of the minimum prices of all valid routes from a to b.
Input

The first line of input contains three integers n, m, q (1 ≤ n, m, q ≤ 105), separated by a single space.

Next n lines contain integers wi (1 ≤ wi ≤ 109).

Next m lines contain pairs of space-separated integers aj and bj (1 ≤ aj, bj ≤ n, aj ≠ bj).

It is guaranteed that there is at most one road connecting the same pair of cities. There is always at least one valid route between any two cities.

Next q lines each describe a query. The format is "a w" or "a b" (1 ≤ a, b ≤ n, 1 ≤ w ≤ 109).

Output

For each query of type "A", output the corresponding answer.

Sample test(s)
input
3 3 3
1
2
3
1 2
2 3
1 3
A 2 3
C 1 5
A 2 3
output
1
2
input
7 9 4
1
2
3
4
5
6
7
1 2
2 5
1 5
2 3
3 4
2 4
5 6
6 7
5 7
A 2 3
A 6 4
A 6 7
A 3 3
output
2
1
5
3
Note

For the second sample, an optimal routes are:

From 2 to 3 it is [2, 3].

From 6 to 4 it is [6, 5, 1, 2, 4].

From 6 to 7 it is [6, 5, 7].

From 3 to 3 it is [3].


0
0
查看评论

UOJ #30. 【CF Round #278】Tourists Tarjan+树链剖分

题目链接:http://uoj.ac/problem/30 题目大意:给定一张无向连通图,每个点有点权,多次询问两个点之间的简单路径上最小点权值的最小值 首先求的是最小点权值的最小值 那么我们肯定要走点权越小的点越好 但是由于求的是简单路径 那么我们就不能经过同一个点两次 那么我们Tarjan...
  • PoPoQQQ
  • PoPoQQQ
  • 2014-12-01 17:24
  • 1779

CodeForces 487E UOJ 30 Tourists Tarjan + 树链剖分

#include #define FOR(i,j,k) for(i=j;i<=k;i++) int read() { int s = 0, f = 1; char ch = getchar(); for (; '0' > ch || ch < &#...
  • huanghongxun
  • huanghongxun
  • 2015-11-20 18:35
  • 818

[省选前题目整理][UOJ 35]后缀排序(后缀数组)

题目链接http://uoj.ac/problem/35思路后缀数组裸题。代码#include <iostream> #include <stdio.h> #include <stdlib.h> #include <string.h> #include...
  • qpswwww
  • qpswwww
  • 2015-04-02 20:32
  • 522

codeforces E. Tourists (树链剖分+tarjan)

E. Tourists time limit per test 2 seconds memory limit per test 256 megabytes input standard input output standard output ...
  • clover_hxy
  • clover_hxy
  • 2017-03-04 20:42
  • 141

Codeforces 487E Tourists

题意:给出一幅图和每个点的权值,每次修改某个点权值或询问两点间所有简单路径上的点权值最小值 思路: 只能看出来tarjan缩点和树剖,然后完全未考虑清楚细节。。似乎建图方法很高级 首先tarjan缩点,对于每个块,新建一个点x,x向所有块内不是深度最小的点连边(借鉴(抄袭)某神犇的方法),然后...
  • wzf_2000
  • wzf_2000
  • 2016-12-15 14:32
  • 129

uoj46. 经营与开发(贪心)

Description 4X概念体系,是指在PC战略游戏中一种相当普及和成熟的系统概念,得名自44个同样以“EX”为开头的英语单词。 eXplore(探索) eXpand(拓张与发展) eXploit(经营与开发) eXterminate(征服) ——维基百科 今次我们着重考虑...
  • kaqiur
  • kaqiur
  • 2016-11-10 15:20
  • 241

UOJ33树上GCD

传送门 官方题解 我写的是点分做法,一开始我是用memset(dp,0,(sizeof dp[0])*t)来清零dp数组的1到t位,但这样第t位刚好没覆盖到,然后就没过大样例。#include<cstdio> #include<cctype> #include<c...
  • zxin__
  • zxin__
  • 2017-08-02 22:42
  • 135

CodeForces - 487E Tourists

题意:询问两点任意路径上点权的最小值,可修改点权 先把所有点双处理一下=造一个新点向所有分量内的点连边,取其中一个点作为父亲,权值是除父亲外点权的最小值(修改时同时修改父亲)=于是可见,任意点双内都是可以乱走的,所以走过新建店相当于对该分量内所有点取min,同时lca为新建点是还要把它爸算...
  • qq_35205305
  • qq_35205305
  • 2016-12-14 13:23
  • 173

CodeForces 487E Tourists

题意: n(10^5)个点的图  旅行者在每次旅行都要买纪念品  每次旅行为u->v的任意简单路径  购买的纪念品为路径上最便宜的纪念品  有q次询问  每次询问要么改变一个点的纪念品价格  要么询问一次旅行所买的纪念品价格 思路...
  • u013351160
  • u013351160
  • 2014-11-27 15:11
  • 1096

[Codeforces 487E]Tourists/[JZOJ4691]旅行/[UOJ#30]Tourists

题目大意给定一个有nn个点mm条边的无向图,每个点有点权wiw_i。 有qq个操作,每次询问所有点xx到点yy的简单路径上最小点权是多少或者将点xx权值改为yy。 1≤n,m,q≤1×105,1≤wi≤1091\le n,m,q\le 1\times 10^5,1\le w_i\le1...
  • a_crazy_czy
  • a_crazy_czy
  • 2016-08-18 19:50
  • 900
    个人资料
    • 访问:177646次
    • 积分:6147
    • 等级:
    • 排名:第4820名
    • 原创:449篇
    • 转载:7篇
    • 译文:0篇
    • 评论:7条
    神犇们的后庭院
    wzq_QwQ http://blog.csdn.net/wzq_QwQ
    vmurder http://blog.csdn.net/vmurder/
    PoPoQQQ http://blog.csdn.net/popoqqq/
    YJQ神犇 http://tarawa.github.io/
    ?神?论文
    http://www.cs.cmu.edu/~rwh/theses/okasaki.pdf