我的启发式合并跑了 40s+

P1600 [NOIP2016 提高组] 天天爱跑步

ReTF @ 2023-10-16 10:50:27

如题,我用的是 O(n\log^2n) 的启发式合并。

从第 9 个点开始就 TLE 了,自测跑了 40s+。

程序是能跑出来的,但是跑的特别慢。

求助大佬我的启发式合并是不是写假了。

#include"bits/stdc++.h"
using namespace std;
#pragma GCC optimize(2)
#define endl '\n'
const int maxn = 3e5+10;
const int lgn = 18;
int n,m,f[maxn][lgn+2],dep[maxn],ans[maxn];
int t[maxn];
multiset<int>s[3][maxn];
vector<int>e[maxn];
int to[3][maxn],dl[3][maxn];
vector<int>add[3][maxn],del[3][maxn];
int delta[3]={1,-1,0};
#define mi multiset<int>::iterator
int cnt;
void dsu(int id,int U,int V){
    //把 u 合并到 v 上
    int &u=to[id][U],&v=to[id][V];
    if(u==v)return;
    if(s[id][u].size()>s[id][v].size())swap(u,v),swap(U,V);
    for(mi it=s[id][u].begin();it!=s[id][u].end();it++)
        s[id][v].insert((*it)+dl[id][u]-dl[id][v]);
    u=v;
}
void dfs(int p,int Fa){
    dep[p]=dep[Fa]+1;
    for(int i=0;i<e[p].size();i++){
        int to=e[p][i];
        if(to==Fa)continue;
        dfs(to,p);
        f[to][0]=p;
    }
}
int Lca(int u,int v){
    if(dep[u]<dep[v])swap(u,v);
    for(int i=lgn;i>=0;i--)
        if(dep[f[u][i]]>=dep[v])
            u=f[u][i];
    if(u==v)return u;
    for(int i=lgn;i>=0;i--)
        if(f[u][i]!=f[v][i])
            u=f[u][i],v=f[v][i];
    return f[u][0];
}
void query(int id,int p,int Fa){
    for(int i=0;i<e[p].size();i++){
        int to=e[p][i];
        if(to==Fa)continue;
        query(id,to,p);
        dsu(id,to,p);
    }
    int pos=to[id][p];
    dl[id][pos]+=delta[id];
    for(int j=0;j<add[id][p].size();j++){
        int to=add[id][p][j]-dl[id][pos];
        s[id][pos].insert(to);
    } 
    for(int j=0;j<del[id][p].size();j++){
        int to=del[id][p][j]-dl[id][pos];
        if(s[id][pos].find(to)!=s[id][pos].end())
            s[id][pos].erase(s[id][pos].find(to));
    } 
    ans[p]+=s[id][pos].count(t[p]-dl[id][pos]);
}
int main(){
    //freopen("P1600_9.in","r",stdin);
    //freopen("ReTF.out","w",stdout);
    ios::sync_with_stdio(0);
    cin.tie(0),cout.tie(0);
    cin>>n>>m;
    for(int i=1,u,v;i<n;i++){
        cin>>u>>v;
        e[u].push_back(v);
        e[v].push_back(u);
    }
    dfs(1,0);
    for(int j=1;j<=lgn;j++)
        for(int i=1;i<=n;i++)
            f[i][j]=f[f[i][j-1]][j-1];
    for(int i=1;i<=n;i++)
        cin>>t[i],to[0][i]=to[1][i]=i;
    for(int i=1,u,v;i<=m;i++){
        cin>>u>>v;
        int Lc=Lca(u,v),dis=dep[u]+dep[v]-dep[Lc]*2;
        add[0][u].push_back(0);
        if(Lc!=1)del[0][f[Lc][0]].push_back(dep[u]-dep[Lc]+1);
        add[1][v].push_back(dis);
        del[1][Lc].push_back(dep[u]-dep[Lc]);
    }
    query(0,1,0);
    query(1,1,0);
    for(int i=1;i<=n;i++)
        cout<<ans[i]<<' ';
}

by cmach_socket @ 2024-02-24 10:35:08

我的树链剖分TLE#20 跑了9s

同为大常数选手


|