[BZOJ3211]花神游历各国&&[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
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
11
11
HINT
对于100%的数据, n ≤ 100000,m≤200000 ,data[i]非负且小于10^9
Source
由于是开方,所以每个数的开放次数不超过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 }
O(∩_∩)O~ (*^__^*) 嘻嘻…… O(∩_∩)O哈哈~