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

3211: 花神游历各国

Time Limit: 5 Sec  Memory Limit: 128 MB
Submit: 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%的数据, n ≤ 100000,m≤200000 ,data[i]非负且小于10^9


 

 

Source

SPOJ2713 gss4 数据已加强

 

由于是开方,所以每个数的开放次数不超过logn次,用树状数组维护前缀和,对于修改操作变为单点修改。

用并查集维护当前节点之前的最近的一个非1节点。

复杂度o(nlog2n)

 

 1 #include<iostream>
 2 #include<cstring>
 3 #include<cstdio>
 4 #include<cstdlib>
 5 #include<cmath>
 6 #include<algorithm>
 7 using namespace std;
 8 int read() {
 9     int x=0;char ch=getchar();
10     while(!isdigit(ch)) ch=getchar();
11     while(isdigit(ch)){x=x*10+ch-'0';ch=getchar();}
12     return x;
13 }
14 int n,m;
15 long long sum[100005];
16 long long a[100005];
17 int fa[100005];
18 int find(int x){return fa[x]==x?fa[x]:fa[x]=find(fa[x]);}
19 int lowbit(int x){return x&(-x);}
20 void add(int x,long long val) {
21     for(int i=x;i<=n;i+=lowbit(i)) sum[i]+=val;
22 }
23 void change(int x,long long val) {
24     for(int i=x;i<=n;i+=lowbit(i)) sum[i]=sum[i]-val+(long long)sqrt(val);
25 }
26 long long query(int x) {
27     long long ans=0; 
28     for(int i=x;i>0;i-=lowbit(i)) ans+=sum[i];
29     return ans;
30 }
31 int main() {
32     n=read();
33     for(int i=1;i<=n;i++) {a[i]=read();add(i,a[i]);}
34     for(int i=1;i<=n;i++) fa[i]=i;
35     m=read();
36     while(m--) {
37         int x=read(),l=read(),r=read();
38         if(x==2) {
39             int now=find(r);
40             while(now>=l) {
41                 change(now,a[now]);
42                 a[now]=sqrt(a[now]);
43                 if(a[now]<=1) fa[now]=find(fa[now-1]);
44                 now=find(fa[now-1]);
45             }
46         }
47         else {
48             printf("%lld\n",query(r)-query(l-1));
49         }
50     }
51     return 0;
52 }
View Code

 

posted @ 2017-11-07 15:26  wls001  阅读(129)  评论(0编辑  收藏  举报