社区讨论

双 log 做法求卡常

P14891Trink参与者 2已保存回复 1

讨论操作

快速查看讨论及其快照的属性,并进行相关操作。

当前回复
1 条
当前快照
1 份
快照标识符
@mk5du5xx
此快照首次捕获于
2026/01/08 19:47
上个月
此快照最后确认于
2026/01/09 13:44
上个月
查看原帖
CPP
#include<bits/stdc++.h>
//#define int long long
#define getchar getchar_unlocked
#define putchar putchar_unlocked
#define constexpr const
using namespace std;
constexpr int N=1e6+5,Inf=N;
__inline void read(int&x){
    char ch=getchar();
    x=0;
    while(!isdigit(ch))
        ch=getchar();
    while(isdigit(ch))
        x=(x<<3)+(x<<1)+(ch^48),ch=getchar();
    return;
}
__inline void write(int val){
    if(val>=10)
        write(val/10);
    putchar((val%10)^48);
    return;
}
__inline void writeln(int x){
	write(x);
	putchar('\n');
	return;
}
int n,not0,ct[N],e[N][2],son[N],vis[N],fa[N],dtot,dfn[N],f[N],dtot_ds,dfn_ds[N],top[N],maxv[N*3],tag[N*3],DEP,P,siz[N],son_ds[N],ans;
int dfs_info(int u){
    int maxsiz=0,v;
    siz[u]=1;
    if(e[u][0]){
        v=e[u][0];
        siz[u]+=dfs_info(v);
        if(siz[v]>maxsiz)
            maxsiz=siz[son_ds[u]=v];
        if(e[u][1]){
            v=e[u][1];
            siz[u]+=dfs_info(v);
            if(siz[v]>maxsiz)
                maxsiz=siz[son_ds[u]=v];
        }
    }
    return siz[u];
}
#define get_sib(x) (e[fa[(x)]][e[fa[(x)]][0]==(x)])
void dfs_chain(int u,int tp){
    dfn_ds[u]=(++dtot_ds),top[u]=tp;
    if(son_ds[u]){
        dfs_chain(son_ds[u],tp);
        int sib=get_sib(son_ds[u]);
        if(sib)
            dfs_chain(sib,sib);
        return;
    }
    return;
}
#define max(a,b) (((a)<(b))?(b):(a))
__inline void addseg(int l,int r){
    for(l+=P-1,r+=P+1;l^1^r;){
        l^=1,r^=1;
        (l&1)&&(maxv[l]++,tag[l]++);
        (~r&1)&&(maxv[r]++,tag[r]++);
        maxv[l>>1]=max(maxv[l],maxv[l^1])+tag[l>>1];
        maxv[r>>1]=max(maxv[r],maxv[r^1])+tag[r>>1];
        if(((l>>=1)^(r>>=1))==1)
            break;
        l^=1,r^=1;
        (l&1)&&(maxv[l]++,tag[l]++);
        (~r&1)&&(maxv[r]++,tag[r]++);
        maxv[l>>1]=max(maxv[l],maxv[l^1])+tag[l>>1];
        maxv[r>>1]=max(maxv[r],maxv[r^1])+tag[r>>1];
        if(((l>>=1)^(r>>=1))==1)
            break;
    }
    for(l>>=1;l;){
        maxv[l]=max(maxv[l<<1],maxv[l<<1|1])+tag[l],l>>=1;
        maxv[l]=max(maxv[l<<1],maxv[l<<1|1])+tag[l],l>>=1;
        maxv[l]=max(maxv[l<<1],maxv[l<<1|1])+tag[l],l>>=1;
        maxv[l]=max(maxv[l<<1],maxv[l<<1|1])+tag[l],l>>=1;
    }
    return;
}
__inline void modify(int x,int k){
    x+=P;
    for(int y=x;y;)
        k-=tag[y>>=1],
        k-=tag[y>>=1],
        k-=tag[y>>=1],
        k-=tag[y>>=1];
    maxv[x]=k;
    for(x>>=1;x;){
        maxv[x]=max(maxv[x<<1],maxv[x<<1|1])+tag[x],x>>=1;
        maxv[x]=max(maxv[x<<1],maxv[x<<1|1])+tag[x],x>>=1;
        maxv[x]=max(maxv[x<<1],maxv[x<<1|1])+tag[x],x>>=1;
        maxv[x]=max(maxv[x<<1],maxv[x<<1|1])+tag[x],x>>=1;
    }
    return;
}
__inline void modifyp(int x,int val){
    return modify(dfn_ds[x],val);
}
__inline void addchain(int x){
    while(x){
        addseg(dfn_ds[top[x]],dfn_ds[x]);
        x=fa[top[x]];
    }
    return;
}
#undef max
__inline void add(int x){
    #define lowbit(x) ((x)&(-(x)))
    for(;x<=n;x+=lowbit(x))
        f[x]++;
    return;
    #undef lowbit
}
__inline int qry(int x){
    #define lowbit(x) ((x)&(-(x)))
    int ret=0;
    for(;x;x-=lowbit(x))
        ret+=f[x];
    return ret;
    #undef lowbit
}
__inline int qry(int l,int r){
    if(l>r)
        return 0;
    else
        return qry(r)-qry(l-1);
}
void dfs(int u){
    dfn[u]=(++dtot);
    if(e[u][0]){
        dfs(e[u][0]);
        if(e[u][1])
            dfs(e[u][1]);
    }
    return;
}
int st=clock();
signed main(){
    read(n);
    n++;
    for(int i=2,mother;i<=n;i++){
        read(mother);
        if(!son[mother]){
            fa[i]=mother;
            e[fa[i]][ct[fa[i]]]=i;
            vis[i]=1,ct[fa[i]]=1;
        }
        else{
            fa[i]=son[mother];
            if(!not0)[[unlikely]]
                not0=i;
        }
        son[mother]=i;
    }
    for(int i=2;i<=n;i++)
        if(!vis[i])
            e[fa[i]][ct[fa[i]]]=i,ct[fa[i]]=1;
    if(!not0)
        not0=Inf;
    dfs(1);
    dfs_info(1),dfs_chain(1,1);
    DEP=__lg(n)+1,P=1<<DEP;
    add(dfn[1]);
    dfn[0]=Inf;
    for(int i=2,sib;i<=n;i++){
        add(dfn[i]);
        sib=get_sib(i);
        if(dfn[sib]<dfn[i])
            modifyp(sib,qry(dfn[fa[i]]+1,dfn[i]-1)+Inf);
        else
            ans=max(ans,qry(dfn[fa[i]]+1,dfn[i]-1));
        addchain(i);
        writeln(max(ans,maxv[1]-Inf)+(not0<=i));/*
        if(i>800000&&1.0*(clock()-st)/CLOCKS_PER_SEC>0.99)[[unlikely]]
            return 0;*/
    }
    return 0;
}
最大点卡到 1.18s 了(评测记录的时间是最大点)。能不能帮我卡进 1s。

回复

1 条回复,欢迎继续交流。

正在加载回复...