蒟蒻求救,我用标记法的线段树,但是比不用标记法的慢??
查看原帖
蒟蒻求救,我用标记法的线段树,但是比不用标记法的慢??
332578
emoheizi楼主2020/7/4 12:56

我使用标记法的线段树理论上应该更快啊,因为我先标记然后在向下查找迭代时处理子区间啊?而不使用标记法的每次都直接向下处理子区间还慢啊?但我在OJ上提交的结果反而是不使用标记法的更快,这是怎么回事啊?请大佬帮忙看看

不使用标记法的代码:

#define MAX_VAL 500000+5
#define MOD_NUM 80112002
#include <bits/stdc++.h>
using namespace std;
class Node{
    public:
        int left,right,val;
        vector<Pair> labels;
};
Node tree[4 * MAX_VAL];

int nums[MAX_VAL],ans,n,m;

void build(int left,int right,int ind){
    tree[ind].left = left,tree[ind].right = right;
    if(left==right) {tree[ind].val = nums[tree[ind].left];return;}
    int mid = left + (right - left)/2;
    build(left,mid,ind*2),build(mid+1,right,ind*2+1);
    tree[ind].val = tree[ind*2].val + tree[ind*2+1].val;
}

int get_sum(int left,int right,int ind){
    Node& node = tree[ind];
    if(node.left>=left&&node.right<=right){return node.val;}
    int ans = 0;
    if(tree[ind*2].right>=left) ans+=get_sum(left,right,ind*2);
    if(tree[ind*2+1].left<=right) ans+=get_sum(left,right,ind*2+1);
    return ans;
}

void add(int ind,int dist,int k){
    tree[ind].val += k;
    if(tree[ind].left==tree[ind].right) return;
    if(dist<=tree[ind*2].right) add(ind*2,dist,k);
    if(dist>=tree[2*ind+1].left) add(ind*2+1,dist,k);
}

bool redn(int& res){
    char ch=getchar();int cof = 1; res=0;
    if(ch==EOF) return false;
    while(ch>'9'||ch<'0') {if(ch=='-') cof = -1;ch=getchar();}
    while(ch>='0'&&ch<='9') res = res*10 + ch-'0',ch=getchar();;
    res *= cof;
    return true;
}
int main(int arg, char **argv)
{
    #ifdef LOCAL
        ifstream in(argv[1]);
        streambuf *cinbuf = cin.rdbuf(); //save old buf
        cin.rdbuf(in.rdbuf());           //redirect cin to file
        freopen("./input/input.in", "r", stdin);
    #endif
    redn(n),redn(m);
    for(int i=1;i<=n;i++) redn(nums[i]);
    build(1,n,1);
    for(int i=1;i<=m;i++){
        int op,x,k;
        redn(op),redn(x),redn(k);
        if(op==1) add(1,x,k);
        if(op==2){
            int ans = get_sum(x,k,1);
            cout<<ans<<endl;
        }
    }
    return 0;
}

使用标记法的:

#define MAX_VAL 500000+5
#include <bits/stdc++.h>
using namespace std;
class Pair{
    public:
        int ind,val;
    Pair(int ind,int val){this->ind=ind;this->val=val;}
};
class Node{
    public:
        int left,right,val;
        vector<Pair> labels;
};
Node tree[4 * MAX_VAL];

int nums[MAX_VAL],ans,n,m;

void build(int left,int right,int ind){
    tree[ind].left = left,tree[ind].right = right;
    if(left==right) {tree[ind].val = nums[tree[ind].left];return;}
    int mid = left + (right - left)/2;
    build(left,mid,ind*2),build(mid+1,right,ind*2+1);
    tree[ind].val = tree[ind*2].val + tree[ind*2+1].val;
}

// use labels
void add(int ind,int dist,int val){
    if(tree[ind].left>dist||tree[ind].right<dist) return;
    tree[ind].val += val;
    tree[ind].labels.push_back(Pair(dist,val));
} 

void pushdown(int ind){
    Node& node = tree[ind];
    for(int i=0;i<node.labels.size();i++){
        Pair& p = node.labels[i];
        int dist = p.ind,val=p.val;
        add(ind*2,dist,val),add(ind*2+1,dist,val);
    }
    node.labels.clear();
}

int get_sum(int left,int right,int ind){
    Node& node = tree[ind];
    pushdown(ind);
    if(node.left>=left&&node.right<=right){return node.val;}
    int ans = 0;
    if(tree[ind*2].right>=left) ans+=get_sum(left,right,ind*2);
    if(tree[ind*2+1].left<=right) ans+=get_sum(left,right,ind*2+1);
    return ans;
}

bool redn(int& res){
    char ch=getchar();int cof = 1; res=0;
    if(ch==EOF) return false;
    while(ch>'9'||ch<'0') {if(ch=='-') cof = -1;ch=getchar();}
    while(ch>='0'&&ch<='9') res = res*10 + ch-'0',ch=getchar();;
    res *= cof;
    return true;
}
int main(int arg, char **argv)
{
    redn(n),redn(m);
    for(int i=1;i<=n;i++) redn(nums[i]);
    build(1,n,1);
    for(int i=1;i<=m;i++){
        int op,x,k;
        redn(op),redn(x),redn(k);
        if(op==1) add(1,x,k);
        if(op==2){
            int ans = get_sum(x,k,1);
            cout<<ans<<endl;
        }
    }
    return 0;
}
2020/7/4 12:56
加载中...