【BZOJ3211】【并查集+树状数组】花神游历各国

Description

  【BZOJ3211】【并查集+树状数组】花神游历各国_第1张图片

Input

  【BZOJ3211】【并查集+树状数组】花神游历各国_第2张图片

Output

每次x=1时,每行一个整数,表示这次旅行的开心度

 

Sample Input

4

1 100 5 5

5

1 1 2

2 1 2

1 1 2

2 2 3

1 1 4

Sample Output

101

11

11
【分析】
开始看一眼觉得线段树可做。
后来看题解用树状数组瞬秒......orzzz,注意到任何一个int都可以在很小的次数下变为1,所以直接暴力单点修改,将变成1的数parent设为它右边的数。
注意,输入中可能会有很多的0....直接写优化不好会T。
 1 #include <iostream>
 2 #include <cstdio>
 3 #include <algorithm>
 4 #include <cstring>
 5 #include <vector>
 6 #include <utility>
 7 #include <iomanip>
 8 #include <string>
 9 #include <cmath>
10 #include <queue>
11 #include <map>
12 
13 const int MAXN = 100000 + 10; 
14 const int MAX = 30000 + 10; 
15 using namespace std;
16 typedef long long ll;
17 int n;
18 ll C[MAXN];
19 int data[MAXN], parent[MAXN];
20 
21 int SQRT(int x){return (int)floor(sqrt((double)x * 1.0));}
22 int lowbit(int x){return x & -x;}
23 void add(int x, int val){
24      while (x <= n){
25            C[x] += val;
26            x += lowbit(x);
27      }
28      return;
29 }
30 ll sum(int x){
31     ll cnt = 0;
32     while (x > 0){
33           cnt += C[x];
34           x -= lowbit(x); 
35     }
36     return cnt;
37 }
38 int find(int x) {return parent[x] == x? x : parent[x] = find(parent[x]);}
39 void init(){
40      memset(C, 0, sizeof(C));
41      scanf("%d", &n);
42      for (int i = 1; i <= n; i++){
43          scanf("%d", &data[i]);
44          add(i, data[i]);
45          parent[i] = i;
46          if (data[i] == 1 || data[i] == 0) parent[i] = i + 1;
47      }
48      parent[n + 1] = n + 1;
49 }
50 void work(){
51      int q;
52      scanf("%d", &q);
53      for (int i = 1; i <= q; i++){
54          int t, x, y;
55          scanf("%d%d%d", &t, &x, &y);
56          if (t == 1) printf("%lld\n", sum(y) - sum(x - 1));
57          else{
58               for (int i = x; i <= y; i = find(i + 1)){
59                   int tmp = data[i];
60                   data[i] = SQRT(data[i]);
61                   add(i, data[i] - tmp);
62                   if (data[i] <= 1) parent[i] = find(i + 1);
63               }
64          }
65      } 
66 }
67  
68 int main(){
69     int T;
70     #ifdef LOCAL
71     freopen("data.txt",  "r",  stdin);
72     freopen("out.txt",  "w",  stdout); 
73     #endif
74     init();
75     work();
76     return 0;
77 }
View Code

 

你可能感兴趣的:(树状数组)