线段树入门题目,单点修改
有几个注意点:
1.主函数开头把stdio同步关了ios::sync_with_stdio(false)不加之前TLE:2000ms,加完之后大概700ms多一点
2.主函数输入的时候cin>>str>>t1>>t2;如果str==“End”的时候,不需要输入t1和t2了,我一开始cin三个连着写,一直WA,改了好久。。。
3.下面程序用了两个更新函数Update_add和Update_sub,其实不需要这么麻烦,对比发现,只是加或减的问题,所以我们只需要写一个Update函数,然后需要减的时候,主函数调用时,把第二个参数加个负号就行了。
//一直WA 不知道哪里错了 懒得改了
//更新 AC了
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn=50010;
int sum[maxn<<2];
int a[maxn];
void BuildTree(int l,int r,int rt) {
if(l==r) {
sum[rt]=a[l];
return ;
}
int m=(l+r)>>1;
BuildTree(l,m,rt<<1);
BuildTree(m+1,r,rt<<1|1);
sum[rt]=sum[rt<<1]+sum[rt<<1|1];
}
int Query(int L,int R,int l,int r,int rt) {
if(l>=L&&r<=R)
return sum[rt];
int m=(l+r)>>1;
int ans=0;
if(L<=m)
ans+=Query(L,R,l,m,rt<<1);
if(R>m)
ans+=Query(L,R,m+1,r,rt<<1|1);
return ans;
}
void Update_add(int L,int C,int l,int r,int rt) {
if(l==r) {
sum[rt]+=C;
return;
}
int m=(l+r)>>1;
if(L<=m)
Update_add(L,C,l,m,rt<<1);
else
Update_add(L,C,m+1,r,rt<<1|1);
sum[rt]=sum[rt<<1]+sum[rt<<1|1];
}
void Update_sub(int L,int C,int l,int r,int rt) {
if(l==r) {
sum[rt]-=C;
return;
}
int m=(l+r)>>1;
if(L<=m)
Update_sub(L,C,l,m,rt<<1);
else
Update_sub(L,C,m+1,r,rt<<1|1);
sum[rt]=sum[rt<<1]+sum[rt<<1|1];
}
int main(void) {
//freopen("E:\\input.txt","r",stdin);
//freopen("E:\\output.txt","w",stdout);
ios::sync_with_stdio(false);
int T,n,t1,t2,kase=0;
string str;
cin>>T;
while(T--) {
memset(sum,0,sizeof sum);
memset(a,0,sizeof a);
cin>>n;
for(int i=1; i<=n; i++)
cin>>a[i];
BuildTree(1,n,1);
kase++;
cout<<"Case "<<kase<<":"<<endl;
while(true) {
cin>>str;
if(str=="End")
break;
cin>>t1>>t2;//这里一直WA 一开始把str t1 和t2的输入写在一起了
if(str=="Query")
cout<<Query(t1,t2,1,n,1)<<endl;
else if(str=="Add")
Update_add(t1,t2,1,n,1);
else
Update_sub(t1,t2,1,n,1);
}
}
return 0;
}