关于指针,常数和线段树
  • 板块学术版
  • 楼主Error_Eric
  • 当前回复9
  • 已保存回复9
  • 发布时间2022/9/25 15:09
  • 上次更新2023/10/27 10:00:25
查看原帖
关于指针,常数和线段树
217300
Error_Eric楼主2022/9/25 15:09

菜,所以想用指针写线段树。

然后 T 了(没开O2)。 Record

然后随便贺了个题解本地对拍,最大数据 Averagetime 稳定在 625ms 左右,题解大概 460ms,(测时用的是 chy-2003 在 github 上的一个对拍代码)。

然后觉得很离谱,下数据本地测了一下。1130ms(但是测试点显示的是 >1.20s)。

有没有人能帮忙康康,是指针写法本身常数大,还是我实现方法常数大。

本地的编译选项是 g++ -std=c++11 -Wall -D LOCAL Main.cpp -o Main

我的代码(马蜂有些诡异,sum是不包含 tag 的区间和,~ 是 pushdown):

#include<iostream>
#include<algorithm>
#include<stdio.h>
#include<vector>
#ifdef LOCAL
#include<chrono>
#endif
using namespace std;
void readln(int &I){
    I=0;char C=getchar();bool f=0;
    while (!isdigit(C))f|=(C=='-'),C=getchar();
    while ( isdigit(C))(I*=10)+=(C-'0'),C=getchar();
    if(f)I=-I;
}
void assert(bool P){if(!P)puts("fkccf");}
int a[100005],n,m,p;
#define ull unsigned long long
#define cur (*cr)
struct C{
    ull v;
    C(){v=0;}C(ull V){v=V;}
};
C operator+ (C ca,C cb){return (ca.v+cb.v)%p;}
C operator+=(C&ca,C cb){return ca=ca+cb;}
C operator* (C ca,C cb){return (ca.v*cb.v)%p;}
C operator*=(C&ca,C cb){return ca=ca*cb;}
struct node{
    int l,r;
    C sum,t2,t1;
    node *ls=NULL,*rs=NULL;
    node(int _L,int _R,C _S,C _A,C _T,node*L,node*R){
        l=_L,r=_R,
        sum=_S,t2=_A,t1=_T,ls=L,rs=R;
    }
    node(int _L,int _R,C _S){
        *this=node(_L,_R,_S,0,1,NULL,NULL);
    }
    node(){ }
};
int len(node&cr){return cr.r-cr.l+1;}
node operator~(node&cr){
    cr.sum*=cr.t1,
    cr.sum+=len(cr)*cr.t2;
    if(cr.ls!=NULL)
        (*cr.ls).t2*=cr.t1,
        (*cr.ls).t1*=cr.t1,
        (*cr.ls).t2+=cr.t2;
    if(cr.rs!=NULL)
        (*cr.rs).t2*=cr.t1,
        (*cr.rs).t1*=cr.t1,
        (*cr.rs).t2+=cr.t2;
    cr.t1=1,cr.t2=0;
    return cr;
}
node operator+(node&na,node&nb){
    ~na,~nb;
    assert(na.r+1==nb.l);
    assert(na.t1.v==1 and nb.t1.v==1 and na.t2.v==0 and nb.t2.v==0);
    return 
        node(na.l,nb.r,na.sum+nb.sum,0,1,&na,&nb);
}
struct segt{
    node*rt;
    void init(int*a,int l,int r){
        rt=new node;build(a,rt,l,r);
    }
    void build(int*a,node*o,int l,int r){
        if(l==r)
            *o=node(l,r,a[l]);
        else {
            int mid=((l+r)>>1);
            node *lson=new node,*rson=new node;
            build(a,lson,l,mid),build(a,rson,mid+1,r),*o=*lson+*rson;
        }
    }
    void add(node*cr,int&l,int&r,int&val){
        if(cr==NULL or r<cur.l or l>cur.r)return;
        ~cur;
        if(l<=cur.l and cur.r<=r)
            cur.t2+=val;
        else 
            add(cur.ls,l,r,val),add(cur.rs,l,r,val),*cr=*cur.ls+*cur.rs;
    }   
    void add(int&l,int&r,int&val){return add(rt,l,r,val);}
    void tim(node*cr,int&l,int&r,int&val){
        if(cr==NULL or r<cur.l or l>cur.r)return;
        ~cur;
        if(l<=cur.l and cur.r<=r)
            cur.t1*=val,cur.t2*=val;
        else 
            tim(cur.ls,l,r,val),tim(cur.rs,l,r,val),*cr=*cur.ls+*cur.rs;
    }
    void tim(int&l,int&r,int&val){return tim(rt,l,r,val);}
    C que(node*cr,int&l,int&r){
        if(cr==NULL or r<cur.l or l>cur.r)return 0;
        ~cur;
        if(l<=cur.l and cur.r<=r)
            return cur.sum;
        else 
            return que(cur.ls,l,r)+que(cur.rs,l,r);
    }
}Tr;
int main(){
    #ifdef LOCAL
    freopen(".\\..\\..\\dt\\P3373_2.in","r",stdin);
    freopen("out.txt","w",stdout);
    std::chrono::milliseconds Clock1, Clock2;
    Clock1 = std::chrono::duration_cast< std::chrono::milliseconds >(
			std::chrono::system_clock::now().time_since_epoch()
			);
    #endif
    readln(n),readln(m),readln(p);
    for(int i=1;i<=n;i++)
        readln(a[i]);
    Tr.init(a,1,n);
    while(m--){
        int op,u,v,w;
        readln(op),readln(u),readln(v);
        switch (op){
        case 1:readln(w),Tr.tim(Tr.rt,u,v,w);break;
        case 2:readln(w),Tr.add(Tr.rt,u,v,w);break;
        case 3:printf("%llu\n",Tr.que(Tr.rt,u,v).v);break;
        }
    }
    #ifdef LOCAL
    Clock2 = std::chrono::duration_cast< std::chrono::milliseconds >(
                    std::chrono::system_clock::now().time_since_epoch()
                    );
    fclose(stdout);
    freopen("con","w",stdout);
    printf("%lld\n",(Clock2-Clock1).count());
    #endif
}
2022/9/25 15:09
加载中...