thinking:做线段树,然后这个线段树里的结点为这个线段的总值。
the reason of reason:1、大数据又用cin,太慢了!!应该用的scanf
2、数组开得不够大,运行失败
题意:
给一个N,然后N个数,表示各个点的值,然后增加、减少、一个点中的值,查找一个线段中的值。
代码:
#include <iostream>
#include <string.h>
using namespace std;
struct ttt{
int right,left,sum;
}t[155000];
int people[55000],sum1;
void creat(int x,int y,int num){
t[num].left=x;
t[num].right=y;
if(x==y){
t[num].sum=people[y];
}else{
creat(x,(x+y)/2,num+num); //(x+y)/2 与(x+y)/2+1 分别是一半的左边与一半的右边
creat((x+y)/2+1,y,num+num+1);
t[num].sum=t[num+num].sum+t[num+num+1].sum;
}
}
void insert(int x,int y,int num){ //给x这个点加y,会使其线段上的所有点都加y
t[num].sum+=y;
if(t[num].left==x&&t[num].right==x)
return ;
else if(x>(t[num].left+t[num].right)/2) //用(x+y)/2 来判断是在左边还是在右边
return insert(x,y,num+num+1);
else
return insert(x,y,num+num);
}
void del(int x,int y,int num){
t[num].sum-=y;
if(t[num].left==x&&t[num].right==x)
return ;
else if(x>(t[num].right+t[num].left)/2)
return del(x,y,num+num+1);
else
return del(x,y,num+num);
}
void Find(int x,int y,int num){
if(t[num].left>=x&&t[num].right<=y){ //之所以不是t[num].left==x&&t[num].right 是因为找的任意区间!!
sum1+=t[num].sum;
}else{
int mid=(t[num].right+t[num].left)/2; //mid为这个线段的中值
if(mid<x){ //如果x-y全部在线段的右边,只查右
Find(x,y,num+num+1);
}else if(mid>=y){ //如果x-y全部在线段的左边,只查左
Find(x,y,num+num);
}else{ //否则都查
Find(x,y,num+num);
Find(x,y,num+num+1);
}
}
}
void find(int x,int y){
sum1=0;
Find(x,y,1);
cout << sum1 << endl;
}
int main(){
freopen("in.txt","r",stdin);
int T,n,m,t1,t2,i,j,k,l;
char gg[20];
cin >> T;
int tt=T;
while(T--){
cout << "Case " << tt-T << ":"<<endl;
memset(people,0,sizeof(people));
memset(t,0,sizeof(t));
cin >> n;
for(i=1;i<=n;i++)
cin >> people[i];
creat(1,n,1); //从第一个结点开始创建一个1-n的线段树
while(cin >> gg){
if(strcmp(gg,"End")==0)break;
scanf("%d%d",&t1,&t2);
if(gg[0]=='Q')find(t1,t2);
else if(gg[0]=='S')del(t1,t2,1);
else if(gg[0]=='A')insert(t1,t2,1);
}
}
return 0;
}