BZOJ[3211]花神游历各国 树状数组+并查集
2017-08-20 21:52
681 查看
题目链接http://www.lydsy.com/JudgeOnline/problem.php?id=3211
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
题目大意:给定一个长度为n的序列,支持区间开平方(向下取整)和区间求和
根号是不支持区间修改的,我们可以选择单点修改区间查询的树状数组,但是这样是O(n^2)的,时间上接受不了
发现一个数x最多开loglogx次根号就会变为1,也就是一个int范围内的数最多开6次根号就会变为1 ,如果某个数变为1,以后可以不对这个数进行操作,修改的总时间复杂度为O(nloglog1e9)
对于每一个已经为0或1的点,以后的每次操作都可以直接跳过这个点,这种操作可以用并查集来实现(同BZOJ2054,疯狂的馒头)对于每一个非0非1的节点i,使f[i]=i,如果某次操作将编号为i的点变为1,则更改f[i]为i+1,在区间修改时,每次从节点i跳到f[i+1]即可
当然这题也可以用线段树打标记来实现。。但因为并查集好写,所以就不写线段树的做法了23333
代码如下:
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
题目大意:给定一个长度为n的序列,支持区间开平方(向下取整)和区间求和
根号是不支持区间修改的,我们可以选择单点修改区间查询的树状数组,但是这样是O(n^2)的,时间上接受不了
发现一个数x最多开loglogx次根号就会变为1,也就是一个int范围内的数最多开6次根号就会变为1 ,如果某个数变为1,以后可以不对这个数进行操作,修改的总时间复杂度为O(nloglog1e9)
对于每一个已经为0或1的点,以后的每次操作都可以直接跳过这个点,这种操作可以用并查集来实现(同BZOJ2054,疯狂的馒头)对于每一个非0非1的节点i,使f[i]=i,如果某次操作将编号为i的点变为1,则更改f[i]为i+1,在区间修改时,每次从节点i跳到f[i+1]即可
细节1:f[n+1]=n+1
细节2:答案会爆int
某sb这题因为没处理好细节T了15次,WA了3次,CE了1次…..当然这题也可以用线段树打标记来实现。。但因为并查集好写,所以就不写线段树的做法了23333
代码如下:
#include<ctype.h> #include<cstdio> #include<cmath> #define N 100500 #define int long long using namespace std; inline int read(){ int f=1,x=0; char c=getchar(); while(!isdigit(c)){if(c=='-')f=-1;c=getchar();} while(isdigit(c)){x=(x<<3)+(x<<1)+c-'0';c=getchar();} return x*f; } int n,m,k,l,r,t,q ,a ,f ; int lowbit(int x){return x&-x;} void add(int x,int v){ while(x<=n){ q[x]=q[x]+v; x=x+lowbit(x); } } long long sum(int x){ long long tmp=0; while(x){ tmp=tmp+q[x]; x=x-lowbit(x); } return tmp; } int find(int x){return f[x]==x?x:f[x]=find(f[x]);} main(){ n=read(); for(int i=1;i<=n;i++) a[i]=read(),add(i,a[i]),f[i]=a[i]<=1?i+1:i; f[n+1]=n+1; m=read(); for(int i=1;i<=m;i++){ k=read();l=read();r=read(); if(k==1) printf("%lld\n",sum(r)-sum(l-1)); else{ for(int j=l;j<=r;j=find(j+1)){ int tmp=(int)sqrt(a[j]); add(j,tmp-a[j]); a[j]=tmp; if(a[j]<=1) f[j]=find(j+1); } } } return 0; }
相关文章推荐
- BZOJ 3211 花神游历各国 树状数组+并查集
- BZOJ 3211 花神游历各国 树状数组+并查集
- BZOJ 3211 花神游历各国 (树状数组+并查集)
- bzoj 3211: 花神游历各国 树状数组+并查集
- BZOJ 3211: 花神游历各国/BZOJ 3038: 上帝造题的七分钟2 树状数组+并查集
- BZOJ3211 花神游历各国(树状数组+并查集)
- [BZOJ3211]花神游历各国&&[BZOJ3038] 上帝造题的七分钟2 树状数组+并查集
- BZOJ 3211 花神游历各国
- 【BZOJ3211】花神游历各国(线段树)
- bzoj3211花神游历各国 线段树
- BZOJ 3038 上帝造题的七分钟2 BZOJ 3211 花神游历各国 题解
- BZOJ3211 花神游历各国 【树状数组 + 并查集】
- bzoj3211 花神游历各国
- 【bzoj3211】花神游历各国
- bzoj3211 花神游历各国
- [BZOJ3211]花神游历各国(线段树+区间开根)
- bzoj3211花神游历各国 线段树
- BZOJ 3211: 花神游历各国
- BZOJ3211 花神游历各国 【树状数组 + 并查集】
- bzoj3211: 花神游历各国