社区讨论

线段树的模板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 条回复,欢迎继续交流。

正在加载回复...