社区讨论
线段树的模板70ptsTLE求调玄关
P3374【模板】树状数组 1参与者 2已保存回复 1
讨论操作
快速查看讨论及其快照的属性,并进行相关操作。
- 当前回复
- 1 条
- 当前快照
- 1 份
- 快照标识符
- @mhj0z9o8
- 此快照首次捕获于
- 2025/11/03 18:56 4 个月前
- 此快照最后确认于
- 2025/11/03 18:56 4 个月前
CPP
#include<bits/stdc++.h>
using namespace std;
const int maxn=500005;
int a[maxn],n,m,tree[4*maxn];
int x,k,y;
int find(int num){
for (int i=1;;i*=2)
if (i>=num)
return i;
}
void buildtree(){
int l=find(n);
for (int i=1;i<=n;i++)
tree[l+i-1]=a[i];
for (int i=l/2;i>=1;i/=2){
for (int j=i;j<=2*i-1;j++)
tree[j]=tree[j*2]+tree[j*2+1];
}
}
void add(int t,int l,int r){
tree[t]+=k;
if (l==r)
return;
else if (x<=(l+r)/2)
return add(2*t,l,(l+r)/2);
else
return add(2*t+1,(l+r+1)/2,r);
}
int solve(int t,int l,int r){
if (l==r)
return tree[t];
int mid=(l+r)/2;
if (y<=mid)//半左
return solve(2*t,l,mid);
else if (x>mid)//半右
return solve(2*t+1,mid+1,r);
else if (x==l)//全左半右
return tree[2*t]+solve(2*t+1,mid+1,r);
else if (y==r)//半左全右
return tree[2*t+1]+solve(2*t,l,mid);
else //半左半右
return solve(2*t,l,mid)+solve(2*t+1,mid+1,r);
}
int main(){
cin>>n>>m;
for (int i=1;i<=n;i++)
cin>>a[i];
buildtree();
int findn=find(n);
while (m--){
int op;
cin>>op;
if (op==1){
cin>>x>>k;
add(1,1,findn);
}
if (op==2){
cin>>x>>y;
cout<<solve(1,1,findn)<<endl;
}
}
return 0;
}
我猜应该是下面的时间复杂度炸了,但是每次求区间和应该最多只会用到一次这种情况啊
CPP else //半左半右
return solve(2*t,l,mid)+solve(2*t+1,mid+1,r);
由于代码是自由发挥的,马蜂混乱请见谅
回复
共 1 条回复,欢迎继续交流。
正在加载回复...