通不过样例的线段树模板求调(一年没碰变废物了呜呜)

P3372 【模板】线段树 1

Christophe_ @ 2023-07-05 20:24:06

// Problem: P3372 【模板】线段树 1
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/P3372
// Memory Limit: 125 MB
// Time Limit: 1000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

#include<bits/stdc++.h>
using namespace std;

#define int long long 

inline int read(){
    int ret=0,f=1; 
    char ch=getchar();
    while(ch<'0'||ch>'9'){ if(ch=='-') f=-f; ch=getchar(); }
    while(ch>='0'&&ch<='9') ret=ret*10+ch-'0',ch=getchar();
    return ret*f;
}
inline void write(int x){        
    if(x<0){ putchar('-'); x=-x; }      
    if(x>9) write(x/10);     
    putchar(x%10+'0');     
}

const int MAXN=1e6+7,minL=1,maxR=1e6+7;

int id=0;

struct Node{
    int ls,rs;
    int val,tag;
}tr[MAXN<<2];

void push_up(int p){
    tr[p].val=tr[tr[p].ls].val+tr[tr[p].rs].val;
}

void push_down(int p,int l,int r){
    if(l>=r) return;

    int mid=(l+r-1)/2;

    if(!tr[p].ls) tr[p].ls=++id;
    if(!tr[p].rs) tr[p].rs=++id;

    tr[tr[p].ls].val+=tr[p].tag*(mid-l+1);
    tr[tr[p].ls].tag+=tr[p].tag;

    tr[tr[p].rs].val+=tr[p].tag*(r-mid);
    tr[tr[p].rs].tag+=tr[p].tag;

    tr[p].tag=0;
}

void add(int l,int r,int x,int p=1,int cl=minL,int cr=maxR){
    if(l==cl&&r==cr){
        tr[p].val+=x*(cr-cl+1);
        tr[p].tag+=x;
        return;
    }
    int mid=(cl+cr-1)/2;
    push_down(p,cl,cr);
    if(r<=mid) add(l,r,x,tr[p].ls,cl,mid);
    else if(l>mid) add(l,r,x,tr[p].rs,mid+1,cr);
    else{
        add(l,mid,x,tr[p].ls,cl,mid);
        add(mid+1,r,x,tr[p].rs,mid+1,cr);
    }
    push_up(p);
}

int qry(int l,int r,int p=1,int cl=minL,int cr=maxR){
    if(l==cl&&r==cr) return tr[p].val;  
    int mid=(cl+cr-1)/2;
    push_down(p,cl,cr);
    if(r<=mid) return qry(l,r,tr[p].ls,cl,mid);
    else if(l>mid) return qry(l,r,tr[p].rs,mid+1,cr);
    else{
        int lans=qry(l,mid,tr[p].ls,cl,mid);
        int rans=qry(mid+1,r,tr[p].rs,mid+1,cr);
        return lans+rans;
    }
}

int n,m;

signed main(){
    n=read(),m=read();

    for(int i=1;i<=n;++i){
        int tmp=read();
        add(i,i,tmp);
    }   

    for(int i=1;i<=m;++i){
        int op=read(),x=read(),y=read();
        if(op==1){
            int k=read();
            add(x,y,k);
        }else{
            write(qry(x,y));
            putchar('\n');
        }
    }

    return 0;
}

动态开点线段树,拆区间写法,瞪了半天不知道哪里错了(


by Althemeta @ 2023-07-05 20:33:16

add和query


by Christophe_ @ 2023-07-05 20:53:38

好奇怪,把动态开点替换掉就能 AC ,这是为什么啊(动态开点为什么会假掉 qwq


by Christophe_ @ 2023-07-05 21:03:09

明白了,id 应该初始化为 1,相当于先开了一个根节点,占用一个编号;

如果初始化为 0 的话左儿子的编号就会与根节点相同,造成错误.


|