[HDU 4027] Can you answer these queries? (线段树+区间开方)

HDU - 4027

给定一个长度为 N 的数列,有M个操作,操作分两种
一是让指定区间每个数都开方,二是询问区间的和


由于每个数都在LL范围内,所以实际上每个数开方的次数不会很多
用线段树维护区间和,开方就暴力到根,然后逐个开方
当发现区间全部都是 1的时候就直接return

坑点:

  1. 所有数都大于 0
  2. 可能出现 l>r的情况,这时候要 swap(l,r)
  3. 每个case最后还要加一个换行
#pragma comment(linker, "/STACK:102400000,102400000")
#include <cstdio>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <cctype>
#include <map>
#include <set>
#include <queue>
#include <bitset>
#include <string>
#include <complex>
using namespace std;
typedef pair<int,int> Pii;
typedef long long LL;
typedef unsigned long long ULL;
typedef double DBL;
typedef long double LDBL;
#define MST(a,b) memset(a,b,sizeof(a))
#define CLR(a) MST(a,0)
#define SQR(a) ((a)*(a))
#define PCUT puts("\n----------")

const int maxn=1e5+10;
struct SegmentTree
{
    struct node
    {
        int l,r;
        LL val;
    } segt[maxn<<2];
    void build(int,int,int=1);
    void update(int,int,int=1);
    LL query(int,int,int=1);
    void maintain(int);
} tree;
LL inpt[maxn];

int main()
{
    #ifdef LOCAL
    freopen("in.txt", "r", stdin);
//  freopen("out.txt", "w", stdout);
    #endif

    int N,M,T=0;
    while(~scanf("%d", &N))
    {
        printf("Case #%d:\n", ++T);
        for(int i=1; i<=N; i++) scanf("%lld", &inpt[i]);
        tree.build(1,N);
        scanf("%d", &M);
        for(int i=0,t,l,r; i<M; i++)
        {
            scanf("%d%d%d", &t, &l, &r);
            if(l>r) swap(l,r);
            if(!t) tree.update(l,r);
            else printf("%lld\n", tree.query(l,r));
        }
        puts("");
    }
    return 0;
}

void SegmentTree::build(int nl, int nr, int np)
{
    node &now = segt[np];
    now.l=nl, now.r=nr;
    if(nl==nr) {now.val = inpt[nl]; return;}
    int mid = (nl+nr)>>1;
    build(nl,mid,np*2);
    build(mid+1,nr,np*2+1);
    maintain(np);
}

void SegmentTree::update(int ql, int qr, int np)
{
    node &now = segt[np];
    if(now.val==now.r-now.l+1) return;
    if(now.l==now.r){now.val=sqrt(now.val); return;}
    int mid=(now.l+now.r)>>1;
    if(ql<=mid) update(ql,qr,np*2);
    if(qr>mid)  update(ql,qr,np*2+1);
    maintain(np);
}

LL SegmentTree::query(int ql, int qr, int np)
{
    node &now = segt[np];
    if(ql<=now.l && now.r<=qr) return now.val;
    LL ans = 0;
    int mid = (now.l+now.r)>>1;
    if(ql<=mid) ans += query(ql,qr,np*2);
    if(qr>mid)  ans += query(ql,qr,np*2+1);
    return ans;
}

void SegmentTree::maintain(int np)
{
    node &now = segt[np];
    if(now.l != now.r)
    {
        node &lson=segt[np*2], &rson=segt[np*2+1];
        now.val = lson.val + rson.val;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值