路径

【题目描述】

给定一个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\n", res);
 98         }
 99     }
100 }

 

 

posted @ 2018-09-04 19:57  iamunstoppable  阅读(372)  评论(0编辑  收藏  举报