首页 > 代码库 > BZOJ 3211 花神游历各国 线段树题解

BZOJ 3211 花神游历各国 线段树题解

BZOJ 3211 花神游历各国 线段树题解

 

3211: 花神游历各国

Time Limit: 5 Sec  Memory Limit: 128 MB
Submit: 2551  Solved: 946
[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

Sample Output

101

11

11

HINT

 

对于100%的数据, n ≤ 100000,m≤200000 ,data[i]非负且小于10^9


 

 

Source

SPOJ2713 gss4 数据已加强

 

  线段树区间修改区间查询,但是因为开方的特殊性,必须要更新到每个单点上。本题每个点最大为109  ,开方五次就已经变成一了,所以开方标记超过五次往下就不用开了。

#include<cstdio>
#include<cmath> 
#include<algorithm>
#define left l,m,rt<<1
#define right m+1,r,rt<<1|1
#define int_ long long
const int maxn=100010;
using namespace std;
struct NODE{
    int_ sum;int mark;
}res[maxn<<2];
void push_up(int rt){
    res[rt].sum=res[rt<<1].sum+res[rt<<1|1].sum;
}
void build(int l,int r,int rt){
    if(l==r){
        scanf("%d",&res[rt].sum);
        return ;
    }
    int m=(l+r)>>1;
    build(left);
    build(right);
    push_up(rt);
}

void update(int L,int R,int l,int r,int rt){
    if(L<=l&&r<=R){
        res[rt].mark++; 
        if(l==r){
            res[rt].sum=sqrt(res[rt].sum);
            return ;    
        }
    }
    if(res[rt].mark<=5){
        int m=(l+r)>>1;
        if(L<=m)update(L,R,left);
        if(R>m)update(L,R,right);
        push_up(rt);
    }
    
}
int_ enquiry(int L,int R,int l,int r,int rt){
    if(L<=l&&r<=R)return res[rt].sum;
    int_ ret=0;int m=(l+r)>>1;
    if(L<=m)ret+=enquiry(L,R,left);
    if(R>m)ret+=enquiry(L,R,right);
    return ret;
}
int main(){
    int n;
    scanf("%d",&n);
    build(1,n,1);
    int m;
    scanf("%d",&m);
    while(m--){
        int x,l,r;
        scanf("%d %d %d",&x,&l,&r);
        if(x==2)update(l,r,1,n,1);
        else printf("%lld\n",enquiry(l,r,1,n,1));
    }
    return 0;
}

 

BZOJ 3211 花神游历各国 线段树题解