ZJ c652: 四、帶修改區間和(MRSQ) 線段樹開根號

線段樹開根號,因開根號相加後不等於相加開根號
所以不能用lazy tag傳值快速更新
只能找到區間的葉節點開根號後push up
這裡可以做一個優化
因為開根號很快就會變成1
所以可以設一個tag往上傳遞
當葉節點的值為1時
將tag設為true
如果修改到tag值為true的點時
就不要理他
以下為code
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define AC ios::sync_with_stdio(0),cin.tie(0);

struct node
{
int l,r;
ll sum;
bool lazy;
void update()
{
sum=sqrt(sum);
}
} st[300000*4+1];

void push_up(int x)
{
st[x].sum=st[x<<1].sum+st[x<<1|1].sum;
st[x].lazy=st[x<<1].lazy&st[x<<1|1].lazy;
}

void build(int x,int l,int r)
{
st[x].l=l,st[x].r=r,st[x].sum=0,st[x].lazy=0;
if(l==r)
{
cin>>st[x].sum;
if(st[x].sum==1) st[x].lazy=1;
}
else
{
int mid=(l+r)>>1;
build(x<<1,l,mid);
build(x<<1|1,mid+1,r);
push_up(x);
}
}

void modify(int x,int l,int r)
{
if(st[x].lazy==1) return;
int L=st[x].l,R=st[x].r;
if(L==R)
{
st[x].update();
if(st[x].sum==1) st[x].lazy=1;
}
else
{
int mid=(L+R)>>1;
if(l<=mid) modify(x<<1,l,r);
if(r>mid) modify(x<<1|1,l,r);
push_up(x);
}
}

ll query(int x,int l,int r)
{
int L=st[x].l,R=st[x].r;
if(L>=l&&R<=r) return st[x].sum;
else
{
int mid=(L+R)>>1;
ll ans=0;
if(l<=mid) ans+=query(x<<1,l,r);
if(r>mid) ans+=query(x<<1|1,l,r);
push_up(x);
return ans;
}
}

int main()
{
AC
int n,q;
cin>>n>>q;
build(1,1,n);
while(q--)
{
int t,l,r;
cin>>t>>l>>r;
if(t) modify(1,l,r);
else cout<<query(1,l,r)<<'\n';
}
}

留言

這個網誌中的熱門文章

TIOJ 1080 . A.逆序數對 (BIT解法)

ZJ d718: Waiting In Line

AtCoder Educational DP Contest E - Knapsack 2