hdu 4027 Can you answer these queries?

题意:给你一段序列,然后有2种操作,0是代表吧LR区间内的数全部去根号,1是代表求和

思路:线段树维护,大那是全部为1的区间需要加特判,以及区间的左右端点需要重新判断

代码:

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int maxn=100005;
LL sum[maxn<<2],as[maxn];

void build(int l,int r,int i)
{
    if(l==r){
        scanf("%lld",&sum[i]);
        return ;
    }
    int mid=(l+r)>>1;
    build(l,mid,i<<1);
    build(mid+1,r,i<<1|1);
    sum[i]=sum[i<<1]+sum[i<<1|1];
}
void update(int L,int R,int l,int r,int i)
{
    if(l==r){
        sum[i]=sqrt((sum[i]));
        return ;
    }
    if(L<=l&&r<=R&&sum[i]==r-l+1)return ;
    int mid=(l+r)>>1;
    if(L<=mid) update(L,R,l,mid,i<<1);
    if(R>mid) update(L,R,mid+1,r,i<<1|1);
    sum[i]=sum[i<<1]+sum[i<<1|1];
}
LL query(int L,int R,int l,int r,int i)
{
    if(L<=l&&r<=R) return sum[i];
    int mid=(l+r)>>1;
    LL cnt=0;
    if(L<=mid) cnt+=query(L,R,l,mid,i<<1);
    if(R>mid) cnt+=query(L,R,mid+1,r,i<<1|1);
    return cnt;
}
int main()
{
    int n,m,cas=1;
    while(~scanf("%d",&n)){
        build(1,n,1);
        scanf("%d",&m);
        int a,b,c;
        printf("Case #%d:\n",cas++);
        for(int i=0;i<m;i++){
            scanf("%d%d%d",&a,&b,&c);
            int bb=min(b,c),cc=max(b,c);
            if(a)printf("%lld\n",query(bb,cc,1,n,1));
            else update(bb,cc,1,n,1);
        }
        printf("\n");
    }
    return 0;
}
/*
10
1 2 3 4 5 6 7 8 9 10
5
0 1 10
1 1 10
1 1 5
0 5 8
1 4 8
*/

 

posted @ 2018-02-25 09:19  啦啦啦天啦噜  阅读(134)  评论(0编辑  收藏  举报