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

Description

Input

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 }

时间: 2024-10-11 21:47:10

【BZOJ3211】【并查集+树状数组】花神游历各国的相关文章

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

原文地址:http://www.cnblogs.com/GXZlegend/p/6809714.html 题目描述 输入 输出 每次x=1时,每行一个整数,表示这次旅行的开心度 样例输入 4 1 100 5 5 5 1 1 2 2 1 2 1 1 2 2 2 3 1 1 4 样例输出 101 11 11 题解 并查集+树状数组,附带一点数学知识 因为√1=1,且一个数x开接近log2(log2x)次平方后就会变成1,这个数是非常小的. 所以我们完全可以暴力修改,只需要知道每次的修改区间中有多少真

BZOJ 3038 上帝造题的七分钟2 (并查集+树状数组)

题解:同 BZOJ 3211 花神游历各国,需要注意的是需要开long long,还有左右节点需要注意一下. #include <cstdio> #include <cmath> #include <iostream> #include <algorithm> using namespace std; typedef long long LL; LL a[100005],c[100005]; int f[100005],n,m,op,l,r,t; int s

[BZOJ 3211]花神游历各国(并查集+树状数组)

Description Solution 树状数组单点修改区间查询 我们知道一个数n最多修改loglogn次就会变为1 并查集维护每个数右边第一个不为1的位置 #include<cstdio> #include<iostream> #include<cstdlib> #include<cstring> #include<cmath> #define MAXN 100005 using namespace std; typedef long lon

Hdu 5458 Stability (LCA + 并查集 + 树状数组 + 缩点)

题目链接: Hdu 5458 Stability 题目描述: 给出一个还有环和重边的图G,对图G有两种操作: 1 u v, 删除u与v之间的一天边 (保证这个边一定存在) 2 u v, 查询u到v的路径上有几条桥. 解题思路: 这个题目有很多次操作,包含查询和删边两类,首先想到的是连通分量加缩点.如果按照顺序来,删边时候求桥就是问题了.所以可以离线处理,然后一边记录答案一边加边缩点. 对于一个图,把连通分量缩成一个点后,这个图就成为了一棵树, 然后深度差就等于桥的数目.查询的时候对于(u, v)

HDU 5458 Stability(双连通分量+LCA+并查集+树状数组)(2015 ACM/ICPC Asia Regional Shenyang Online)

题目大意:给一个N个点M条边的无向图,有Q个询问:1.删掉a.b之间所存在的边:2.询问有多少条边,单独删掉之后a与b不再连通. 思路:脑洞大开. 对于询问,首先想到的就是a与b之间有多少桥(割边),然后想到双连通分量,然而删边是个坑爹的问题,于是我们离线倒着来,把删边变成加边. 双连通分量这种东西呢,其实缩点连起来之后,就是一棵树辣. 然后询问两个点的时候,设根到点x的距离为dep[x],a.b的最近公共祖先为lca(a, b),那么询问query(a, b) = dep[a] + dep[b

花神游历各国 题解(小清新线段树/树状数组+并查集)

众所周知,这是一道小清新线段树 然而可以用树状数组水过去且跑得飞快 看到区间开方第一反应肯定是线段树懒标记区间修改之类的,但是这个东西似乎确凿不可维护 所以考虑暴力循环单点修改->T飞 于是我们关注一下开方本身的特殊性 我们知道,如果每次向下取整,一个数经过多次操作最终会变成1(或0) 事实上,大概经过 log(logx)次就会变成1 这是什么概念呢?经过博主测试,1e9只要经过五次开方取整就会变成1 那么接下来就能够利用1每次不必再操作优化复杂度 可以维护一个类似链表的结构,指向下一个>1的

BZOJ 3211 花神游历各国 线段树题解

BZOJ 3211 花神游历各国 线段树题解 3211: 花神游历各国 Time Limit: 5 Sec  Memory Limit: 128 MBSubmit: 2551  Solved: 946[Submit][Status][Discuss] Description Input 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

[BZOJ3211]花神游历各国&amp;&amp;[BZOJ3038] 上帝造题的七分钟2 树状数组+并查集

3211: 花神游历各国 Time Limit: 5 Sec  Memory Limit: 128 MBSubmit: 4057  Solved: 1480[Submit][Status][Discuss] Description Input 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 HINT 对于100%的数据,

BZOJ 3211 花神游历各国 树状数组+并查集

题目大意:花神对每一个国家有一个喜爱程度,有的时候他会对连续的一段国家进行访问,求他的喜爱程度的和:有的时候他会对连续的一段国家产生厌恶,喜爱程度变成sqrt(x)下取整. 思路:乍一看好像是RMQ问题,用线段树就可以水过,但是开根号的标记怎么下传?这是一个严重的问题,所以我们要换一个思路. 注意到开根号有一个有趣的性质:sqrt(1) = 1,sqrt(0) = 0,而且所有的数字经过有限次的开根号运算都会变成1.这个性质就很好了.我们对每一个点暴力开根号,然后当这个店的点权变成1的时候就打一