又是个线段树的题目,简单的更新查询
#include <iostream>
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
//线段树是一个二叉树,深度是d=log2(n)+1;
//开数组的话就要开到2^d-1个;
const int N=1e6+9;
int A[N],sum,n;
struct node
{
int left,right,people;
}SS[N];//用一个结构体记录每个线段树的左结点 右结点,还有这个区间一共多少人
void insert(int tt) //初始化整个线段树,从下往上更新
{
if(SS[tt].left==SS[tt].right)
{
SS[tt].people=A[SS[tt].left];
return;
}
int mid=(SS[tt].left+SS[tt].right)/2;
SS[tt*2].left=SS[tt].left;
SS[tt*2].right=mid;
insert(tt*2);
SS[tt*2+1].left=mid+1;
SS[tt*2+1].right=SS[tt].right;
insert(tt*2+1);
SS[tt].people=SS[tt*2].people+SS[tt*2+1].people;
}
void add(int a,int b,int t) // 变更每个结点人数,人数增加的时候b>=0,人数减少的时候b<0
{
if(SS[t].left==SS[t].right)
{
SS[t].people+=b;
return;
}
int mid=(SS[t].left+SS[t].right)/2;
if(a<=mid) add(a,b,t*2);
if(a>mid) add(a,b,t*2+1);
SS[t].people=SS[t*2].people+SS[t*2+1].people;// 从下往上更新
}
void Que(int l,int r,int t) //查询l-r的人数,用sum记录
{
if(SS[t].left>=l && SS[t].right<=r)
{
sum+=SS[t].people;
return;
}
int mid=(SS[t].left+SS[t].right)/2;
if(l<=mid) Que(l,r,t*2);
if(r>mid) Que(l,r,t*2+1);
}
int main()
{
int T,a1,b1,i,flag,cc=1;
char s[200];
scanf("%d",&T);
while(T--)
{
flag=0;
memset(SS,0,sizeof(SS));
scanf("%d",&n);
for(i=1;i<=n;i++)
scanf("%d",&A[i]);
SS[1].left=1; SS[1].right=n;
insert(1);
while(scanf("%s",s),strcmp(s,"End")!=0)
{
scanf("%d %d",&a1,&b1);
if(flag==0) printf("Case %d:\n",cc++);
flag=1;
if(strcmp(s,"Add")==0)
add(a1,b1,1);
else if(strcmp(s,"Sub")==0)
add(a1,-1*b1,1);
else if(strcmp(s,"Query")==0)
{
sum=0;
Que(a1,b1,1);
printf("%d\n",sum);
}
}
}
return 0;
}