西⽐拉先知系统
题目描述
西⽐拉先知系统是⼀个强⼤的⼼灵指数监测⽹絡,能以声像扫描主动监控市⺠的⼼智与精神状态。为了判定出更复杂的⼈类⼼理参数,西⽐拉系统纳⼊了不同于既存⼈类规范的超群⼈格──不会随意和他⼈产⽣共鸣,也不会感情⽤事,能以⾮⼈类的眼光来俯瞰并裁定⼈类。
被纳⼊的超群⼈格会相互影响,共同处理数据。他们之间具体的影响⽅式形如⼀张⽆向图,如果你对⼀个节点进⾏操作,和这个节点相邻的节点也会受到相同的影响。
操作有⼀种:使⼀个节点的权值加上。
同时你还希望询问⼀个节点的权值(每⼀个节点的初始权值为0)。
被纳⼊的超群⼈格会相互影响,共同处理数据。他们之间具体的影响⽅式形如⼀张⽆向图,如果你对⼀个节点进⾏操作,和这个节点相邻的节点也会受到相同的影响。
操作有⼀种:使⼀个节点的权值加上。
同时你还希望询问⼀个节点的权值(每⼀个节点的初始权值为0)。
输入
第⼀⾏读⼊n,m,Q,表⽰节点个数和边数,以及操作和询问的总数。
接下来m⾏,每⾏两个数ui,vi表⽰ui,vi之间有连边。
接下来Q,每⾏先读⼊⼀个type
type=0表⽰⼀个询问,读⼊⼀个x,表⽰询问x节点的权值。
type=1表⽰⼀个操作,读⼊x,y,表⽰将x节点的权值加上y。(与x相邻的节点权值也要加上y)
接下来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 }