1. 程式人生 > 實用技巧 >西⽐拉先知系統

西⽐拉先知系統

西⽐拉先知系統

時間限制:2Sec記憶體限制: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