链接网址:http://www.tyvj.cn/Problem_Upload.asp?id=1324
#include <iostream>
#include <cstdio>
using namespace std;
#define max(a,b) a>b?a:b
// N为最大结点个数
#define N 200005
struct LineTree // 线段的结构
{
int l,r; // 线段的左右边界
int ans; // 需要计算的结果,本题为最大值
LineTree *lchild,*rchild; //指向左右子树的指针
};
int pos; //建立线段树时用来确定对应的线段
LineTree mem[2*N]; //保存所有的线段
int num[N]; //各个结点的初始值
LineTree *CreateTree(int a,int b) //建立区间为[a,b]的线段
{
int mid;
LineTree *s=&mem[pos++];
s->l=a;
s->r=b;
if(b-a>=1) //不是叶子结点线段
{
mid=(a+b)/2;
s->lchild=CreateTree(a,mid);
s->rchild=CreateTree(mid+1,b);
s->ans=(s->lchild->ans+s->rchild->ans);
}
else
s->ans=num[s->l]; //叶子结点
return s;
}
void update(LineTree *s,int a,int b) //将点a的值增加或者减少b
{
if(s->r==s->l) //是叶子结点
{
s->ans=b; //修改叶子结点
return;
}
if(s->lchild->r>=a) update(s->lchild,a,b); //递归修改左边
else if(s->rchild->l<=a) update(s->rchild,a,b); //递归修改右边边
s->ans=s->lchild->ans+s->rchild->ans; //修改中间结点
}
int search(LineTree *s,int a,int b) //查询区间[a,b]的最大值
{
if(s->l==a && s->r==b) return s->ans; //刚好是所求区间
int mid=(s->l+s->r)/2;
if(b<=mid) return search(s->lchild,a,b); //在左边
else if(mid<a) return search(s->rchild,a,b); //在右边
else return (search(s->lchild,a,mid)+search(s->rchild,mid+1,b));//左右都有
}
int main()
{
int i,n,m,a,b;
scanf("%d", &n);
for(i=1;i<=n;i++)
scanf("%d",num+i);
LineTree *s=CreateTree(1,n);
scanf("%d",&m);
while(m--)
{
scanf("%d%d",&a,&b);
printf("%0.2f\n",3.14*search(s,a,b));
update(s,(a+b)/2,0);
}
return 0;
}