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

11 篇文章 0 订阅
10 篇文章 0 订阅

题目链接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]即可

细节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[N],a[N],f[N];
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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值