西⽐拉先知系统

西⽐拉先知系统

时间限制: 2 Sec  内存限制: 128 MB

题目描述

西⽐拉先知系统是⼀个强⼤的⼼灵指数监测⽹絡,能以声像扫描主动监控市⺠的⼼智与精神状态。为了判定出更复杂的⼈类⼼理参数,西⽐拉系统纳⼊了不同于既存⼈类规范的超群⼈格──不会随意和他⼈产⽣共鸣,也不会感情⽤事,能以⾮⼈类的眼光来俯瞰并裁定⼈类。
被纳⼊的超群⼈格会相互影响,共同处理数据。他们之间具体的影响⽅式形如⼀张⽆向图,如果你对⼀个节点进⾏操作,和这个节点相邻的节点也会受到相同的影响。
操作有⼀种:使⼀个节点的权值加上。
同时你还希望询问⼀个节点的权值(每⼀个节点的初始权值为0)。

输入

第⼀⾏读⼊n,m,Q,表⽰节点个数和边数,以及操作和询问的总数。
接下来m⾏,每⾏两个数ui,vi表⽰ui,vi之间有连边。
接下来Q,每⾏先读⼊⼀个type
type=0表⽰⼀个询问,读⼊⼀个x,表⽰询问x节点的权值。
type=1表⽰⼀个操作,读⼊x,y,表⽰将x节点的权值加上y。(与x相邻的节点权值也要加上y)

输出

对于每⼀个询问输出⼀⾏,表⽰该节点的权值。

样例输入

4 4 4
1 2
1 3
1 4
2 3
1 1 1
0 2
1 3 3
0 2

样例输出

1
4

提示

n,m,Q≤3×105,y≤1000

题解

  根号分治,一个绝妙的点子。记录每个点的的入度,总共有m条边,所以入度超过sqrt(m)的点数必然不超过sqrt(m),根据这个特性把整个图分为入度不大于sqrt(m)的点和入度大于sqrt(m)的两部分。

  两部分的操作:对于入度不超过sqrt(m)的点,暴力更新与之相邻的每个点的权值a[],因为其入度不超过sqrt(m),所以与之相邻的点不超过sqrt(m)个;对于入度超过sqrt(m)的点,这部分点有两个权值a[],b[],a[]是正常更新来的权值,b[]是直接更新的权值,也就是每次的type=1,x入度大于sqrt(m)时,更新a[],b[],但是当x入度不超过sqrt(m)时,入度超过sqrt(m)的点的a[]会被更新,但b[]不会被更新。

  两部分的查询:对于所有点,其权值为其自身的a[]和与之相邻的入度大于sqrt(m)的点的权值b[]的和。

  使用这种方法,代码的时间复杂为O(n·sqrt(m)),再也不用担心超时啦~~~

  1 #pragma GCC optimize(3,"Ofast","inline")
  2 #include <map>
  3 #include <set>
  4 #include <time.h>
  5 #include <stack>
  6 #include <queue>
  7 #include <cmath>
  8 #include <vector>
  9 #include <cstdio>
 10 #include <string>
 11 #include <cstring>
 12 #include <iostream>
 13 #include <algorithm>
 14 #define fi first
 15 #define se second
 16 #define IL inline
 17 #define RG register
 18 #define MP(a,b) make_pair(a,b)
 19 #define PI acos(-1)
 20 #define Mod 1000000007
 21 #define EPS 1e-5
 22 using namespace std;
 23 typedef long long LL;
 24 typedef unsigned long long ULL;
 25 typedef double DB;
 26 typedef pair<int, int> PR;
 27 const int N = 300009;
 28 const int M = 400009;
 29 int gx[] = {0, 0, 1, -1};
 30 int gy[] = {1, -1, 0, 0};
 31 int n, m, q, d[N], a[N], b[N];
 32 vector<int> g1[N], g2[N];
 33 PR edge[N];
 34 class Init
 35 {
 36     public:
 37         IL int mabs(int x)
 38         {
 39             return x < 0 ? -x : x;
 40         }
 41         IL int gcd(int a, int b)
 42         {
 43             return b == 0 ? a : gcd(b, a%b);
 44         }
 45         IL int lcm(int a, int b)
 46         {
 47             return a * b / gcd(a, b);
 48         }
 49         IL LL ksm(LL a, LL b)
 50         {
 51             LL tmp = a % Mod, sum = 1;
 52             while(b)
 53             {
 54                 if(b & 1)
 55                     sum = (sum * tmp) % Mod;
 56                 tmp = (tmp * tmp) % Mod;
 57                 b >>= 1;
 58             }
 59             return sum % Mod;
 60         }
 61         IL int read()
 62         {
 63             int num = 0; bool flag = 0; char c;
 64             while((c=getchar())==' ' || c=='\n' || c=='\r');
 65             if(c == '-') flag = 1; else num = c - '0';
 66             while(isdigit(c=getchar()))
 67                 num = num * 10LL + c - '0';
 68             return flag ? -num : num;
 69         }
 70         IL void print(LL x)
 71         {
 72             if(x < 0) putchar('-'), x = -x;
 73             if(x > 9) print(x/10);
 74             putchar(x%10+'0');
 75         }
 76     private:
 77 
 78 }Init;
 79 int main(void)
 80 {
 81     n = Init.read(); m = Init.read(); q = Init.read();
 82     for(int i = 1; i <= m; i++)
 83     {
 84         edge[i].fi = Init.read();
 85         edge[i].se = Init.read();
 86         d[edge[i].fi]++; d[edge[i].se]++;
 87         g1[edge[i].fi].push_back(edge[i].se);
 88         g1[edge[i].se].push_back(edge[i].fi);
 89     }
 90     for(int i = 1; i <= m; i++)
 91     {
 92         if(d[edge[i].se] > sqrt(m)) g2[edge[i].fi].push_back(edge[i].se);
 93         if(d[edge[i].fi] > sqrt(m)) g2[edge[i].se].push_back(edge[i].fi);
 94     }
 95     for(int i = 1; i <= q; i++)
 96     {
 97         int v = Init.read();
 98         if(v == 1)
 99         {
100             int x = Init.read(), y = Init.read();
101             if(d[x] > sqrt(m)) a[x] += y, b[x] += y;
102             else
103             {
104                 a[x] += y;
105                 for(int j = 0; j < g1[x].size(); j++)
106                     a[g1[x][j]] += y;
107             }
108         }
109         else
110         {
111             int x = Init.read();
112             int ans = a[x];
113             for(int j = 0; j < g2[x].size(); j++)
114                 ans += b[g2[x][j]];
115             printf("%d\n", ans);
116         }
117     }
118     return 0;
119 }
View Code

 

posted @ 2020-08-07 18:49  Johnny-English  阅读(230)  评论(0编辑  收藏  举报