线段树70分求助
查看原帖
线段树70分求助
468029
dfxgbm楼主2021/10/2 16:57

我的想法是结点维护前缀和,并进行区间查询和更新,但是总是4,5,7三个点WA

#include <cstdio>
#include <algorithm>
#include <cstring>
#define long long long
#define lc(x) (x)*2
#define rc(x) (x)*2+1
const int M=100001;
using namespace std;
struct seg_tree {
    long val,tag;
    seg_tree():val(0),tag(0) {}
};
//线段树结点中保存前缀和
seg_tree node[M*4];
int n,a[M];
inline void push_down(int k,int l,int r) {
    int child_len=(r-l+1)/2;
    node[lc(k)].val+=(long)child_len*node[k].tag;
    node[rc(k)].val+=(long)child_len*node[k].tag;
    node[lc(k)].tag+=node[k].tag;
    node[rc(k)].tag+=node[k].tag;
    node[k].tag=0;
}

void update(int st,int end,int val,int k=1,int l=1,int r=n) {
    if(l>end||r<st)    return;
    if(l>=st&&r<=end) {
        node[k].val+=(long)val*(r-l+1);
        node[k].tag+=(long)val;
        return;
    }
    push_down(k,l,r);
    int mid=(l+r)/2;
    update(st,end,val,lc(k),l,mid);
    update(st,end,val,rc(k),mid+1,r);
    node[k].val=node[lc(k)].val+node[rc(k)].val;
}

long query(int st,int end,int k=1,int l=1,int r=n) {
    if(l>end||r<st)    return 0;
    if(l>=st&&r<=end) {
        return node[k].val;
    }
    push_down(k,l,r);
    int mid=(l+r)/2;
    long L=query(st,end,lc(k),l,mid);
    long R=query(st,end,rc(k),mid+1,r);
    return L+R;
}

int main(){
    int m,i;
    long sum=0;
    static char q[7];
    scanf("%d%d",&n,&m);
    //将n扩大为2的倍数方便求解
    int t=n;
    for(i=0; (1<<i)<n; i++);
    n=(1<<i);
    for(int i=1; i<=t; i++) {
        scanf("%d",&a[i]);
        sum+=(long)a[i];
        update(i,i,sum);
    }
    for(int i=1; i<=n*2; i++)   node[i].tag=0;
    while(m--) {
        int i;
        scanf("%s%d",q,&i);
        if(strcmp(q,"Modify")==0) {
            int x;
            scanf("%d",&x);
            update(i,n,x-a[i]);
            a[i]=x;
        }
        else    printf("%lld\n",query(1,i));
    }
    return 0;
}
2021/10/2 16:57
加载中...