[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 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
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; iscanf("%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;
    }
}

你可能感兴趣的:(线段树)