/*********
线段树:
战舰的耐久度 不超过2的63次方
说明只要对某一区间的数 最多开根号64次向下取整 值就变成1,不在变化
这个就是该题的优化部分
************/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#define min1(a,b) a<b?a:b;
#define ll unsigned long long
using namespace std;
const int maxn = 1e5+5000;
struct node
{
ll l;
ll r;
ll e;
ll cnt;
} Segtr[4*maxn];
void build(ll rt, ll l, ll r)
{
Segtr[rt].l = l;
Segtr[rt].r = r;
Segtr[rt].cnt = 0;
Segtr[rt].e = 0;
if(l == r)
{
scanf("%lld", &Segtr[rt].e);
return ;
}
ll mid = (l+r)/2;
build(rt*2+1, l, mid);
build(rt*2+2, mid+1, r);
Segtr[rt].e = Segtr[rt*2+1].e +Segtr[rt*2+2].e;
}
void update(ll rt, ll L, ll R)
{
ll l = Segtr[rt].l;
ll r = Segtr[rt].r;
if(Segtr[rt].cnt >= 64)return;
if(l == r)
{
Segtr[rt].cnt++;
Segtr[rt].e = (ll)sqrt((double)Segtr[rt].e);
return ;
}
ll mid = (l+r)/2;
if(R <= mid)
{
update(rt*2+1, L, R);
}
else if(L > mid)
{
update(rt*2+2, L, R);
}
else
{
update(rt*2+1, L, mid);
update(rt*2+2, mid+1, R);
}
Segtr[rt].e = Segtr[rt*2+1].e+Segtr[rt*2+2].e;
Segtr[rt].cnt = min1(Segtr[rt*2+1].cnt, Segtr[rt*2+2].cnt);
}
ll query(ll rt, ll L, ll R)
{
ll l = Segtr[rt].l;
ll r = Segtr[rt].r;
if(Segtr[rt].cnt >= 64)
{
return (R-L+1);
}
ll ret = 0;
if(L == l && R == r)
{
return Segtr[rt].e;
}
ll mid = (l+r)/2;
if(R <= mid)
{
ret += query(rt*2+1, L, R);
}
else if(L > mid)
{
ret += query(rt*2+2, L, R);
}
else
{
ret += query(rt*2+1, L, mid);
ret += query(rt*2+2, mid+1, R);
}
return ret;
}
int main()
{
ll N, M;
ll cnt = 0;
while(~scanf("%lld", &N))
{
build(0, 1, N);
scanf("%lld", &M);
printf("Case #%lld:\n", ++cnt);
for(ll i = 0; i < M; i++)
{
ll op, x, y;
scanf("%lld %lld %lld",&op, &x, &y);
if(x > y)swap(x, y);//注意题目要求 ,题目给的是第x和第y之间 的 战舰 进行操作, 不是给你左右端点
if(op == 0ll)
{
update(0ll, x, y);
}
else
{
ll ans = query(0ll, x, y);
printf("%lld\n", ans);
}
}
printf("\n");
}
return 0;
}
HDU 4027 Can you answer these queries?(线段树+思维)
最新推荐文章于 2020-08-04 20:41:22 发布