zoukankan      html  css  js  c++  java
  • 路径

    【题目描述】

    给定一个n个点每个点度数不超过2的无向图,支持两种操作

    1.加入一条边[l,r],保证加入后图依然满足每个点度不超过2

    2.求长度在[l,r]之间的不经过重复点的路径有多少条

        注意:这里的路径长度定义为经过的点数而不是边数

    【输入】

    第一行三个正整数n,m,q表示点数,初始边数和操作数

    接下来m行每行两个整数u,v表示u到v有一条边

    接下来q行,每行三个整数op l r

    【输出】

    对于每个op=2输出答案

    【样例】

    path1.in

    path1.out

    8 5 8

    1 2

    2 3

    4 5

    5 6

    7 8

    2 2 3

    1 4 6

    2 3 3

    2 1 2

    1 1 7

    2 3 5

    1 3 8

    2 1 8

    7

    4

    14

    9

    34

    path2.in

    path2.out

    4 0 5

    1 1 2

    1 2 3

    1 3 4

    1 4 1

    2 1 4

    16

    大样例见下发文件path3.in/out,path4.in/out

    【数据范围及约定】

    对于100%的数据 1≤n,m,q≤500000 1≤l≤r≤n

    性质1:没有修改操作

    性质2:任意时刻一个联通块内任意两点之间路径唯一

    性质3:任意时刻一个联通块内的点编号连续

    下表给出了各测试点的数据规模和约定

    编号

    n,m

    q

    性质1

    性质2

    性质3

    1

    300

    300

    2

    3

    4

    5000

    2000

    5

    6

    5000

    7

    8

    9

    100000

    100000

    10

    11

    12

    13

    200000

    14

    15

    200000

    16

    17

    18

    19

    20

    500000

    500000

    意思就是说只有简单环和链。

    两条链合并,就是加两个等差数列和区间加法。

    合并成环,就是加一个等差数列。

      1 #include <bits/stdc++.h>
      2 using namespace std;
      3 #define M 500010
      4 #define LL long long
      5 inline int read() {
      6     char ch = getchar(); int x = 0, f = 1;
      7     while(ch < '0' || ch > '9') {
      8         if(ch == '-') f = -1;
      9         ch = getchar();
     10     }
     11     while('0' <= ch && ch <= '9') {
     12         x = x * 10 + ch - '0';
     13         ch = getchar();
     14     }
     15     return x * f;
     16 }
     17 int fa[M], sz[M];
     18 bool vis[M];
     19 LL q[M * 4], A1[4 * M], D[4 * M];
     20 inline int Find(int x) {
     21     return fa[x] == x ? x : fa[x] = Find(fa[x]);
     22 }
     23 inline void update(int l, int r, int o, LL a1, LL d) {
     24     int len = r - l + 1;
     25     q[o] += (1ll * (a1 + a1 + 1ll * (len - 1) * d) * len / 2ll);
     26     A1[o] += a1; D[o] += d;
     27 }
     28 inline void pushdown(int l, int mid, int r, int o) {
     29     LL a1 = A1[o], d = D[o];
     30     if(a1 != 0 || d != 0) {
     31         update(l, mid, 2 * o, a1, d);
     32         update(mid + 1, r, 2 * o + 1, a1 + 1ll * (mid - l + 1) * d, d);
     33         A1[o] = D[o] = 0;
     34     }
     35 }
     36 inline void Add(int l, int r, int o, int x, int y, LL a1, LL d) {
     37     if(x <= l && r <= y) {
     38         update(l, r, o, a1, d);
     39         return;
     40     }
     41     int mid = (l + r) / 2;
     42     pushdown(l, mid, r, o);
     43     int Lnum = 0;
     44     if(x <= mid) Lnum = min(mid, y) - x + 1;
     45     if(x <= mid) Add(l, mid, 2 * o, x, min(mid, y), a1, d);
     46     if(y > mid) Add(mid + 1, r, 2 * o + 1, max(mid + 1, x), y, a1 + d * Lnum, d);
     47     q[o] = q[2 * o] + q[2 * o + 1];
     48 }
     49 inline LL query(int l, int r, int o, int x, int y) {
     50     if(x <= l && r <= y) {
     51         return q[o];
     52     }
     53     int mid = (l + r) / 2;
     54     LL ret = 0;
     55     pushdown(l, mid, r, o);
     56     if(x <= mid) ret += query(l, mid, 2 * o, x, y);
     57     if(y > mid) ret += query(mid + 1, r, 2 * o + 1, x, y);
     58     return ret;
     59 }
     60 int main() {
     61     int n = read(), m = read(), q = read();
     62     for(int i = 1; i <= n; ++ i) {
     63         fa[i] = i; sz[i] = 1;
     64     }
     65     Add(1, n, 1, 1, 1, n, 0);
     66     for(int tt = 1; tt <= m + q; ++ tt) {
     67         int op = 1, l, r;
     68         if(tt > m) op = read();
     69         l = read(), r = read();
     70         if(op == 1) {
     71             if(l == r) continue;
     72             if(Find(l) != Find(r)) {
     73                 int p = Find(l), q = Find(r);
     74                 int x = sz[p], y = sz[q];
     75                 if(sz[p] > sz[q]) swap(p, q);
     76                 fa[p] = q; sz[q] += sz[p];
     77                 if(2 <= min(x, y) + 1) {
     78                     Add(1, n, 1, 2, min(x, y) + 1, 1, 1);
     79                 }
     80                 if(min(x, y) + 2 <= max(x, y) + 1) {
     81                     Add(1, n, 1, min(x, y) + 2, max(x, y) + 1, min(x, y), 0);
     82                 }
     83                 if(max(x, y) + 2 <= x + y) {
     84                     Add(1, n, 1, max(x, y) + 2, x + y, min(x, y) - 1, -1);
     85                 }
     86             }
     87             else {
     88                 int x = sz[Find(l)];
     89                 vis[Find(l)] = 1;
     90                 if(2 <= x) {
     91                     Add(1, n, 1, 2, x, 1, 1);
     92                 }
     93             }
     94         }
     95         else {
     96             LL res = query(1, n, 1, l, r);
     97             printf("%lld
    ", res);
     98         }
     99     }
    100 }
  • 相关阅读:
    Mysql查询语句,select,inner/left/right join on,group by.....[例题及答案]
    Java IO实现文件(及文件夹)的复制 原创代码【精】
    [精华帖]Java接口怎么定义?如何使用?【实例讲解】
    Java面向对象中this关键字详解 意义+实例讲解【hot】
    linux系统编程之进程(三):进程复制fork,孤儿进程,僵尸进程
    linux系统编程之进程(二):进程生命周期与PCB(进程控制块)
    linux系统编程之进程(一):进程与程序
    linux系统编程之文件与IO(八):文件描述符相关操作-dup,dup2,fcntl
    linux系统编程之文件与IO(七):时间函数小结
    linux系统编程之文件与IO(六):实现ls -l功能
  • 原文地址:https://www.cnblogs.com/iamqzh233/p/9588131.html
Copyright © 2011-2022 走看看