西⽐拉先知系統
阿新 • • 發佈:2020-08-07
西⽐拉先知系統
時間限制:2Sec記憶體限制:128 MB題目描述
西⽐拉先知系統是⼀個強⼤的⼼靈指數監測⽹絡,能以聲像掃描主動監控市⺠的⼼智與精神狀態。為了判定出更復雜的⼈類⼼理引數,西⽐拉系統納⼊了不同於既存⼈類規範的超群⼈格──不會隨意和他⼈產⽣共鳴,也不會感情⽤事,能以⾮⼈類的眼光來俯瞰並裁定⼈類。被納⼊的超群⼈格會相互影響,共同處理資料。他們之間具體的影響⽅式形如⼀張⽆向圖,如果你對⼀個節點進⾏操作,和這個節點相鄰的節點也會受到相同的影響。
操作有⼀種:使⼀個節點的權值加上。
同時你還希望詢問⼀個節點的權值(每⼀個節點的初始權值為0)。
輸入
第⼀⾏讀⼊n,m,Q,表⽰節點個數和邊數,以及操作和詢問的總數。接下來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