HDU - 4027 http://acm.hdu.edu.cn/showproblem.php?pid=4027
题意:更新的时候把要求区间内的值都更新为自己开根号,查询时查询区间和。
思路: 感觉自己有个不好的习惯,有题目没思路时老是容易去看题解或是discuss,这个习惯真的要改一下。
这个题由于是根号,所以必须得更新到点,然后会发现,每次开根号一个数会很快变成1,这时再对这段区间开根号是毫无意义的,所以记录下区间和为长度的部分,到这部分就不用更新了。(如果这里不加以考虑会tle)
然后就是sqrt的问题,这个函数是这样的 double sqrt(double n),所以如果用long long型塞进去会有问题,最好是改成n*1.0。
/*
区间更新(这个区间更新还是需要更新到点的,但是需要优化)
区间查询
*/
#include <cstdio>
#include <iostream>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
#define ll long long
const int maxn = 1e5+10;
ll d[maxn],v[maxn<<2];
int n;
void build(int l,int r,int id)
{
v[id] = 0;
if(l == r) {v[id] = d[l]; return;}
int m = l+r>>1;
build(l,m,id<<1);
build(m+1,r,id<<1|1);
v[id] = v[id<<1] + v[id<<1|1];
}
void up(int ul,int ur,int id,int l,int r)
{
if(l > ur || r < ul) return;
if(v[id] == r-l+1) return;
if(l == r) {v[id] = sqrt(v[id]*1.0); return;}
int m = l+r>>1;
if(ul <= m) up(ul,ur,id<<1,l,m);
if(ur > m) up(ul,ur,id<<1|1,m+1,r);
v[id] = v[id<<1] + v[id<<1|1];
}
ll qu(int ql,int qr, int id, int l, int r)
{
if(l > qr || r < ql) return 0;
if(l >= ql && r <= qr) return v[id];
int m = l+r>>1;
ll ans = 0;
if(ql <= m) ans += qu(ql,qr,id<<1,l,m);
if(qr > m) ans += qu(ql,qr,id<<1|1,m+1,r);
return ans;
}
int main()
{
int q,a,b,c,kase = 1;
while(~scanf("%d",&n))
{
for(int i = 1; i <= n; i++)
scanf("%I64d",&d[i]);
build(1,n,1);
scanf("%d",&q);
printf("Case #%d:\n",kase++);
while(q--)
{
scanf("%d%d%d",&a,&b,&c);
if(b > c) swap(b,c);
if(!a) up(b,c,1,1,n);
else printf("%I64d\n",qu(b,c,1,1,n) );
}
printf("\n");
}
return 0;
}