• 离家出走


      

    离家出走


    时间限制: 2000 ms         内存限制: 256M

    【题目描述】

    企鹅豆豆考试爆零了

    心态爆炸的他准备离家出走

    贫穷的企鹅国有 N 座城市

    一开始城市之间没有道路连接不能通行

    随着时间推移,一些道路逐渐建立

    但由于国家财力实在不足

    所以随时随地任意两座城市最多只有一条路径可以互相到达

    每次豆豆考试爆炸,他都想从考场里跑到离考场最远的一个城市去

    当然豆豆每次都会想知道

    最远的且可以到达的城市离考场所在城市有多远?

    奇妙的事情是,企鹅国的每一条道路长度都是 1

    【输入】

    第一行一个整数 type,表示数据类型。

    接下来第二行两个整数 N,Q,表示城市个数和事件个数。

    接下来 Q 行,先读入一个整数 op,表示事件类型。

    如果 op=1,那么接着有两个整数 u,v

    表示城市 u 和城市 v 之间建立了一条新的道路。

    如果 op=2,那么接着有一个整数 u

    表示这次考试的考场在城市 u

    豆豆想知道最远的城市离考场有多远。

    如果 type=1,令上一次 op=2 时的答案为 lastans,

    那么对于输入的每一个 u 或者 v 都需要异或上 lastans

    (lastans 初始为 0。)

    如果 type=0,那么不需要进行其余额外操作。

    【输出】

    对于每次 op=2 的询问

    输出一行一个整数表示离考场最远的城市距离考场的距离。

    【输入样例】

    0
    5 10
    1 4 5
    2 3
    2 5
    2 1
    1 5 3
    1 1 4
    2 3
    2 5
    1 5 2
    2 1

    【输出样例】

    0
    1 
    0
    3
    2
    3

    【提示】

    对于 20%的输入数据:N≤5000,Q≤10000。

    对于 50%的输入数据:N≤100000,Q≤200000。

    对于另外 20%的输入数据:type=0。

    对 100%的输入数据:N≤300000,Q≤500000,

    道路的修建会满足,随时随地图中不存在环。


    毒瘤...

    反正就是个并查集 + 倍增lca + 启发式合并,复杂度Qlog²n

    有个性质:合并两个树,新的直径端点一定在原直径端点上。

    还有个:树上一点能到达的最远点一定是直径端点

    然后合并的时候启发式合并,更新小树上的dis,fa

    同时更新大树根上记录的直径端点。

    A了但是这数据有毒,暴力合并比正解还快...没有一条链数据来卡。

      1 #include <cstdio>
      2 #include <algorithm>
      3 const int N = 400010;
      4 
      5 struct Edge {
      6     int v, nex;
      7 }edge[N << 1]; int top;
      8 int dis[N], siz[N], fa[N][20], l[N], r[N], e[N];
      9 int ufs[N], lm;
     10 inline void init(const int &n) {
     11     lm = 19;
     12     while((1 << lm) > n) {
     13         lm--;
     14     }
     15     for(int i = 1; i <= n; i++) {
     16         ufs[i] = i;
     17         siz[i] = 1;
     18         dis[i] = 1; /// error : 0
     19         l[i] = r[i] = i; /// error : i
     20     }
     21     return;
     22 }
     23 inline void add(int x, int y) {
     24     top++;
     25     edge[top].v = y;
     26     edge[top].nex = e[x];
     27     e[x] = top;
     28     return;
     29 }
     30 inline int find(int x) {
     31     if(ufs[x] == x) {
     32         return x;
     33     }
     34     return ufs[x] = find(ufs[x]);
     35 }
     36 void DFS(int x, int d, int f) { /// error : NO f
     37     dis[x] = d;
     38     for(int i = 1; i <= lm; i++) {
     39         fa[x][i] = fa[fa[x][i - 1]][i - 1];
     40     }
     41     for(int i = e[x]; i; i = edge[i].nex) {
     42         int y = edge[i].v;
     43         if(y == f) {
     44             continue;
     45         }
     46         fa[y][0] = x;
     47         DFS(y, d + 1, x);
     48     }
     49     return;
     50 }
     51 inline int lca(int x, int y) {
     52     if(dis[x] > dis[y]) {
     53         std::swap(x, y);
     54     }
     55     int i = lm;
     56     while(i >= 0 && dis[x] != dis[y]) {
     57         if(dis[x] <= dis[fa[y][i]]) {
     58             y = fa[y][i];
     59         }
     60         i--;
     61     }
     62     if(x == y) {
     63         return x;
     64     }
     65     i = lm;
     66     while(i >= 0 && fa[x][0] != fa[y][0]) {
     67         if(fa[x][i] != fa[y][i]) {
     68             x = fa[x][i];
     69             y = fa[y][i];
     70         }
     71         i--;
     72     }
     73     return fa[x][0];
     74 }
     75 inline int dist(int x, int y) {
     76     return dis[x] + dis[y] - (dis[lca(x, y)] << 1);
     77 }
     78 inline void merge(int x, int y) {
     79     int tx = find(x);
     80     int ty = find(y);
     81     if(siz[tx] < siz[ty]) {
     82         std::swap(x, y);
     83         std::swap(tx, ty);
     84     }
     85     /// x >= y
     86     fa[y][0] = x;
     87     DFS(y, dis[x] + 1, x);
     88     siz[tx] += siz[ty];
     89 
     90     int A = l[tx], B = l[ty];
     91     int C = r[tx], D = r[ty];
     92     int len = dist(A, C);
     93     int a = A, b = C;
     94     int t = dist(A, B);
     95     if(len < t) {
     96         len = t;
     97         b = B;
     98     }
     99     t = dist(A, D);
    100     if(len < t) {
    101         len = t;
    102         b = D;
    103     }
    104     t = dist(C, B);
    105     if(len < t) {
    106         len = t;
    107         a = C;
    108         b = B;
    109     }
    110     t = dist(B, D);
    111     if(len < t) {
    112         len = t;
    113         a = B;
    114         b = D;
    115     }
    116     t = dist(C, D);
    117     if(len < t) {
    118         a = C;
    119         b = D;
    120     }
    121     l[tx] = a;
    122     r[tx] = b;
    123     add(x, y);
    124     add(y, x);
    125     ufs[ty] = tx;
    126     return;
    127 }
    128 inline int ask(int x) {
    129     int L = l[find(x)], R = r[find(x)];
    130     return std::max(dist(x, L), dist(x, R));
    131 }
    132 int main() {
    133     int k;
    134     int n, T;
    135     scanf("%d", &k);
    136     scanf("%d%d", &n, &T);
    137     init(n);
    138     int f, x, y, lastans = 0;
    139     while(T--) {
    140         scanf("%d", &f);
    141         if(f == 1) {
    142             scanf("%d%d", &x, &y);
    143             if(k) {
    144                 x ^= lastans;
    145                 y ^= lastans;
    146             }
    147             if(find(x) != find(y)) {
    148                 merge(x, y);
    149             }
    150         }
    151         else {
    152             scanf("%d", &x);
    153             if(k) {
    154                 x ^= lastans;
    155             }
    156             lastans = ask(x);
    157             printf("%d
    ", lastans);
    158         }
    159     }
    160     return 0;
    161 }
    AC代码
  • 相关阅读:
    zoj 2406 Specialized FourDigit Numbers
    hdu 1016 Prime Ring Problem(深度优先搜索)
    【ObjectiveC】08self关键字
    【ObjectiveC】09空指针和野指针
    【零基础学习iOS开发】【01前言】01开篇
    【零基础学习iOS开发】【01前言】03前景和难易度分析
    多线程编程1NSThread
    【零基础学习iOS开发】【02C语言】02第一个C语言程序
    多线程编程2NSOperation
    【零基础学习iOS开发】【01前言】02准备
  • 原文地址:https://www.cnblogs.com/huyufeifei/p/9350580.html
Copyright © 2020-2023  润新知