关于平板电视运行速度问题
查看原帖
关于平板电视运行速度问题
654577
RainySoul楼主2025/1/21 07:45

在我的认知中,运行速度方面应该是 gp_hash_table > cc_hash_table > unordered_map

但是在此题中我尝试使用 gp_hash_table 提速,却发现 cc_hash_table > unordered_map > gp_hash_table

甚至几个 unordered_map 只需要跑 200 ms 的点 gp_hash_tableT\text{T} 飞了,这是为什么?

以下是使用 cc_hash_table 的代码,其余的只需要略微修改:

#include<bits/stdc++.h>
#include<bits/extc++.h>
#define inf 1e18
#define int long long
using namespace std;
using namespace __gnu_pbds;
const int N=100010,lgN=50;
inline int read(){
    int x=0,f=1;
    char c=getchar();
    while(c<'0'||c>'9'){
        if(c=='-')f=-1;
        c=getchar();
    }
    while(c>='0'&&c<='9'){
        x=x*10+c-'0';
        c=getchar();
    }
    return x*f;
}

//树剖
struct SegementTree1{//这个是求dis用的树剖线段树
    int w[N<<2];
    inline void update(int u,int l,int r,int x,int k){
        if(l==r){
            w[u]=k;
            return;
        }
        int mid=(l+r)>>1;
        if(x<=mid)update(u*2,l,mid,x,k);
        else update(u*2+1,mid+1,r,x,k);
        w[u]=w[u*2]+w[u*2+1];
    }
    inline int query(int u,int l,int r,int x,int y){
        if(x<=l&&r<=y)return w[u];
        int mid=(l+r)>>1;
        int res=0;
        if(x<=mid)res+=query(u*2,l,mid,x,y);
        if(y>mid)res+=query(u*2+1,mid+1,r,x,y);
        return res;
    }
}T1;
struct zyx{int to,w;};
vector<zyx> e[N];
struct csq{int u,v,w;};
vector<csq> edge;
int n,Q,cnt;
int fa[N],sz[N],dep[N],son[N],top[N],dfn[N],rnk[N];
inline void dfs1(int now,int fz){
    fa[now]=fz;
    sz[now]=1;
    dep[now]=dep[fz]+1;
    for(int i=0;i<(int)e[now].size();i++){
        int to=e[now][i].to;
        if(to==fz)continue;
        dfs1(to,now);
        sz[now]+=sz[to];
        if(sz[to]>sz[son[now]])son[now]=to;
    }
}
inline void dfs2(int now,int topf){
    top[now]=topf;
    dfn[now]=++cnt;
    rnk[cnt]=now;
    if(!son[now])return;
    dfs2(son[now],topf);
    for(int i=0;i<(int)e[now].size();i++){
        int to=e[now][i].to;
        if(to==fa[now]||to==son[now])continue;
        dfs2(to,to);
    }
}
int getdis(int x,int y){
    int res=0;
    while(top[x]!=top[y]){
        if(dep[top[y]]>dep[top[x]])swap(x,y);
        res+=T1.query(1,1,n,dfn[top[x]],dfn[x]);
        x=fa[top[x]];
    }
    if(dep[y]>dep[x])swap(x,y);
    res+=T1.query(1,1,n,dfn[y]+1,dfn[x]);
    return res;
}
//树剖

//建点分树
struct SegementTree2{
    int w[N*lgN],ls[N*lgN],rs[N*lgN],lazy[N*lgN];
    int rt[N],tot;
    inline void pushdown(int u){
        if(!lazy[u])return;
        w[ls[u]]+=lazy[u];
        w[rs[u]]+=lazy[u];
        lazy[ls[u]]+=lazy[u];
        lazy[rs[u]]+=lazy[u];
        lazy[u]=0;
    }
    inline void update1(int &u,int l,int r,int x,int k){//单点修改
        if(!u)u=++tot;
        if(l==r){
            w[u]=k;
            return;
        }
        int mid=(l+r)>>1;
        pushdown(u);
        if(x<=mid)update1(ls[u],l,mid,x,k);
        else update1(rs[u],mid+1,r,x,k);
        w[u]=min(w[ls[u]],w[rs[u]]);
    }
    inline void update2(int &u,int l,int r,int x,int y,int k){//区间加
        if(!u)u=++tot;
        if(x<=l&&r<=y){
            w[u]+=k;
            lazy[u]+=k;
            return;
        }
        int mid=(l+r)>>1;
        pushdown(u);
        if(x<=mid)update2(ls[u],l,mid,x,y,k);
        if(y>mid)update2(rs[u],mid+1,r,x,y,k);
        w[u]=min(w[ls[u]],w[rs[u]]);
    }
    inline void build(int &u,int l,int r){
        if(!u)u=++tot;
        w[u]=inf;
        if(l==r)return;
        int mid=(l+r)>>1;
        build(ls[u],l,mid);
        build(rs[u],mid+1,r);
    }
}T2;
int maxnson[N],vis[N],FA[N],sum,rt,dep2[N];
cc_hash_table<int,int> dfn2[N],sz2[N];
int tcnt;
inline void getrt(int now,int fz){
    maxnson[now]=0;
    sz[now]=1;
    for(int i=0;i<(int)e[now].size();i++){
        int to=e[now][i].to;
        if(to==fz||vis[to])continue;
        getrt(to,now);
        sz[now]+=sz[to];
        maxnson[now]=max(maxnson[now],sz[to]);
    }
    maxnson[now]=max(maxnson[now],sum-sz[now]);
    if(maxnson[now]<maxnson[rt])rt=now;
} 
inline void dfs(int from,int now,int fa){
    dfn2[from][now]=++tcnt;//这里存一下每个点在以from为根的连通块中的dfn序与sz
    sz2[from][now]=1;
    for(int i=0;i<(int)e[now].size();i++){
        int to=e[now][i].to;
        if(to==fa||vis[to])continue;
        dfs(from,to,now);
        sz2[from][now]+=sz2[from][to];
    }
}
inline void solve(int now){
    vis[now]=1;tcnt=0;
    dfs(now,now,0);
    T2.build(T2.rt[now],1,sz2[now][now]);
    for(int i=0;i<(int)e[now].size();i++){
        int to=e[now][i].to;
        if(vis[to])continue;
        rt=0,sum=sz2[now][to];
        getrt(to,now);
        FA[rt]=now;dep2[rt]=dep2[now]+1;//dep2记录每个点在点分树上的深度
        solve(rt);
    }
}
//建点分树

//处理询问
inline int getans(int x){
    int res=inf,temp=x;
    while(temp){
        res=min(res,getdis(temp,x)+T2.w[T2.rt[temp]]/*直接查询点分树上temp子树的最小值*/);
        temp=FA[temp];
    }
    return res;
}
inline void Update(int x,int k){
    int temp=x;
    while(temp){
        int DIS=getdis(x,temp);
        if(k==1)T2.update1(T2.rt[temp],1,sz2[temp][temp],dfn2[temp][x],DIS);
        else if(k==-1)T2.update1(T2.rt[temp],1,sz2[temp][temp],dfn2[temp][x],inf);
        temp=FA[temp];
    }
}
inline void calc(int x,int y,int w){
    int p=x,q=y;
    if(dep2[p]<dep2[q])swap(p,q);
    while(dep2[p]>dep2[q])p=FA[p];
    while(p!=q)p=FA[p],q=FA[q];
    while(p){
        if(dfn2[p][x]<dfn2[p][y])swap(x,y);
        T2.update2(T2.rt[p],1,sz2[p][p],dfn2[p][x],dfn2[p][x]+sz2[p][x]-1,w);
        p=FA[p];
    }
}
int yes[N],tot;
//处理询问
signed main(){
    ios::sync_with_stdio(0);
    cin.tie(0);cout.tie(0);
    n=read(),Q=read();
    for(int i=1;i<n;i++){
        int u=read(),v=read(),w=read();
        e[u].push_back((zyx){v,w});
        e[v].push_back((zyx){u,w});
        edge.push_back((csq){u,v,w});
    }
    dfs1(1,0);dfs2(1,1);//树剖
    for(int i=0;i<n-1;i++){
        int u=edge[i].u,v=edge[i].v,w=edge[i].w;
        if(dep[u]<dep[v])swap(u,v);
        T1.update(1,1,n,dfn[u],w);
    }//下放边权
    rt=0,maxnson[rt]=inf,sum=n;
    getrt(1,0);
    solve(rt);
    for(int i=1;i<=Q;i++){
        int op=read();
        if(op==1){
            int q=read();
            if(tot==0)cout<<"-1\n";
            else cout<<getans(q)<<'\n';
        }
        else if(op==2){
            int u=read();
            if(yes[u]){
                yes[u]=0;
                tot--;
                Update(u,-1);
            }
            else if(!yes[u]){
                yes[u]=1;
                tot++;
                Update(u,1);
            }
        }
        else if(op==3){
            int a=read(),b=read(),w=read();
            if(dep[a]<dep[b])swap(a,b);
            calc(a,b,w-getdis(a,b));
            T1.update(1,1,n,dfn[a],w);
        }
    }
    return 0;
}
2025/1/21 07:45
加载中...