[bzoj3211]花神游历各国

12 篇文章 0 订阅
12 篇文章 0 订阅

Description

写一个数据结构兹瓷区间求和和区间开方。
n<=10^5,m<=2*10^5,ai<=10^9

Solution

区间开平方?暴力开呗。
反正10^9也不需要开多少次,只不过常数大了点罢了。
用线段树维护区间和,还有区间标记,表示这个区间是不是还有可以开方的数(1&0)。
当然,用树状数组维护和再用并查集来打标记也是可以的,而且常数更小。
不过,有一个迷之问题,为什么一定要把0给标记,不然会惨绝人寰地超时?
表示奥妙重重。

Code

#include<cmath>
#include<cstdio>
#include<cstring>
#include<algorithm> 
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define N 100005
using namespace std;
typedef long long ll;
struct note{ll v;bool bz;}t[N*3];
int n,m,z,x,y,a[N];
void back(int v,int x) {
    t[v].v=x;if (x==1||x==0) t[v].bz=1;
}
note merge(note y,note z) {
    note x;x.v=y.v+z.v;x.bz=y.bz&&z.bz;return x;
}
void build(int v,int l,int r) {
    if (l==r) {
        back(v,a[l]);
        return;
    }
    int m=(l+r)/2;
    build(v*2,l,m);build(v*2+1,m+1,r);
    t[v]=merge(t[v*2],t[v*2+1]);
}
void revise(int v,int l,int r) {
    if (t[v].bz) return;
    if (l==r) {
        a[l]=sqrt(a[l]);
        back(v,a[l]);
        return;
    }
    int m=(l+r)/2;
    revise(v*2,l,m);revise(v*2+1,m+1,r);
    t[v]=merge(t[v*2],t[v*2+1]);
}
void change(int v,int l,int r,int x,int y) {
    if (t[v].bz) return;
    if (l==x&&r==y) {revise(v,l,r);return;}
    int m=(l+r)/2;
    if (y<=m) change(v*2,l,m,x,y);
    else if (x>m) change(v*2+1,m+1,r,x,y);
    else change(v*2,l,m,x,m),change(v*2+1,m+1,r,m+1,y);
    t[v]=merge(t[v*2],t[v*2+1]);
}
ll find(int v,int l,int r,int x,int y) {
    if (l==x&&r==y) return t[v].v;
    int m=(l+r)/2;
    if (y<=m) return find(v*2,l,m,x,y);
    else if (x>m) return find(v*2+1,m+1,r,x,y);
    else return find(v*2,l,m,x,m)+find(v*2+1,m+1,r,m+1,y);
}
int main() {
    scanf("%d",&n);
    fo(i,1,n) scanf("%d",&a[i]);
    build(1,1,n);
    for(scanf("%d",&m);m;m--) {
        scanf("%d%d%d",&z,&x,&y);
        if (z==1) printf("%lld\n",find(1,1,n,x,y));
        else change(1,1,n,x,y);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值