求助LCT巨佬:到底慢在哪了?
查看原帖
求助LCT巨佬:到底慢在哪了?
557754
Kalenist楼主2023/8/12 16:34

平凡的线段树分治+LCT,一开始只有 60pts60pts。看题解发现写法几乎一样,但这份代码就是卡在 60pts60pts…… 求助到底是哪里慢了?

#define N 100010
#define lc k<<1
#define rc k<<1|1
#define isroot(x) (ch[fa[x]][0]!=x&&ch[fa[x]][1]!=x)
#define get(x) (ch[fa[x]][1]==x)
inline void rev(int x){if(x) tag[x]^=1,swap(ch[x][0],ch[x][1]);}
inline int read()
{
    register int x=0,c=getchar();
    while(!isdigit(c)) c=getchar();
    while(isdigit(c)) x=(x<<1)+(x<<3)+(c^48),c=getchar();
    return x;
}

inline void pushup(int x)
{
    if(!x) return;mxid[x]=x;
    mxid[x]=mxid[val[mxid[x]]>val[mxid[ch[x][0]]]?x:ch[x][0]];
    mxid[x]=mxid[val[mxid[x]]>val[mxid[ch[x][1]]]?x:ch[x][1]];
    return;
}

inline void pushdown(int k)
{
    if(!tag[k]) return;
    rev(ch[k][0]),rev(ch[k][1]);
    return void(tag[k]=0);
}

inline void update(int x)
{
    while(!isroot(x)) node[++node[0]]=x,x=fa[x];
    node[++node[0]]=x;
    while(node[0]) pushdown(node[node[0]--]);
    return;
}

inline void zug(int x)
{
    int y=fa[x],z=fa[y],k=get(x);
    if(!isroot(y)) ch[z][get(y)]=x;
    ch[y][k]=ch[x][!k],fa[ch[x][!k]]=y;
    ch[x][!k]=y,fa[y]=x,fa[x]=z;
    return pushup(y),pushup(x);
}

inline void splay(int x)
{
    update(x);
    for(int f=fa[x];!isroot(x);zug(x),f=fa[x])
        if(!isroot(f)) zug(get(x)==get(f)?f:x);
    return;
}

inline void access(int x)
{
    for(int p=0;x;p=x,x=fa[x])
        splay(x),ch[x][1]=p,pushup(x);
    return;
}

inline void makeroot(int x)
{
    access(x),splay(x);
    return rev(x);
}

inline int findroot(int x)
{
    access(x),splay(x);
    while(ch[x][0]) x=ch[x][0],pushdown(x);
    splay(x);return x;
}

inline void link(int x,int y)
{
    makeroot(x);
    access(y),splay(y),fa[x]=y;
    return;
}

inline void cut(int x,int y)
{
    makeroot(x);
	access(y),splay(y);
    ch[y][0]=fa[x]=0;
    return pushup(y);
}

inline int query(int x,int y)
{
    makeroot(x);
    access(y),splay(y);
    return mxid[y];
}

inline void modify(int k,int l,int r,int x,int y,int nw)
{
    if(l >= x && r <= y) {h[k].push_back(nw);return;}
    int mid=l+r>>1;
    if(x <= mid) modify(lc,l,mid,x,y,nw);
    if(mid < y) modify(rc,mid+1,r,x,y,nw);
    return;
}

inline void maintain(int x)
{
    int nw;
    if(findroot(fr[x]) != findroot(to[x]))
        link(fr[x],x),link(to[x],x),sta[++top]=pair<int,bool>(x,0),ans+=val[x];
    else if(val[nw=query(fr[x],to[x])] > val[x])
    {
        cut(fr[nw],nw),cut(to[nw],nw),sta[++top]=pair<int,bool>(nw,1),ans-=val[nw];//first存虚点,second存删还是加。fr,to为边的端点
        link(fr[x],x),link(to[x],x),sta[++top]=pair<int,bool>(x,0),ans+=val[x];
    }
    return;
}

inline void undone(int lim)
{
    for(pair<int,bool> x=sta[top];top>lim;x=sta[--top])
        if(x.second) link(fr[x.first],x.first),link(to[x.first],x.first),ans+=val[x.first];
        else cut(fr[x.first],x.first),cut(to[x.first],x.first),ans-=val[x.first];
    return;
}

inline void solve(int k,int l,int r)
{
    int cpy=top,mid=l+r>>1;
    for(unsigned int i=0;i<h[k].size();i++) maintain(h[k][i]);
    if(l == r) printf("%lld\n",ans);
    else solve(lc,l,mid),solve(rc,mid+1,r);
    return undone(cpy);
}

int main()
{
    n=read(),m=read(),q=read(),tot=n;
    For(i,1,m)
    {
        f[i]=read(),t[i]=read(),d[i]=read();
        lst[i]=1,lstid[i]=++tot,val[tot]=d[i];
		fr[tot]=f[i],to[tot]=t[i];//建立虚点,边权转点权
    }
    For(i,1,q)
    {
        int id=read(),nd=read();
        if(lst[id] < i) modify(1,1,q,lst[id],i-1,lstid[id]);
        lst[id]=i,lstid[id]=++tot,val[tot]=nd;
		fr[tot]=f[id],to[tot]=t[id];
    }For(i,1,m) modify(1,1,q,lst[i],q,lstid[i]);
    solve(1,1,q);
    return 0;
}

2023/8/12 16:34
加载中...