2 条题解
-
0
神秘启发式合并解法?
#include<bits/stdc++.h> using namespace std; typedef long long ll; int n; vector<int> e[200010]; int lowbit(int x){ return x&(-x); } struct BIT{ int tr[200010]; void add(int x,int v){ for(int i=x;i<=n;i+=lowbit(i))tr[i]+=v; } int find(int x){ int ans=0; for(int i=x;i;i-=lowbit(i))ans+=tr[i]; return ans; } }tr; int sz[200010],son[200010]; void dfs(int x,int xfa){ sz[x]=1;son[x]=-1; for(int y:e[x])if(y^xfa){ dfs(y,x); if(son[x]==-1||sz[y]>sz[son[x]])son[x]=y; sz[x]+=sz[y]; } } ll f[200010],g[200010]; map<pair<int,int>,ll> mp; void add(int x,int xfa,int v){ tr.add(x,v); for(int y:e[x])if(y^xfa)add(y,x,v); } void dfs2(int x,int xfa,int fl){ for(int y:e[x])if((y^xfa)&&(y^son[x])){ dfs2(y,x,1); mp[{x,y}]=tr.find(x-1); add(y,x,-1); } if(~son[x]){ dfs2(son[x],x,1); mp[{x,son[x]}]=tr.find(x-1); for(int y:e[x])if((y^xfa)&&(y^son[x])){ add(y,x,1); } f[x]=tr.find(x-1); } if(fl)tr.add(x,1); else{ for(int y:e[x])if((y^xfa)&&((y^son[x])))add(y,x,-1); } for(int y:e[x])if(y^xfa)g[x]+=g[y]+f[y]; } void dfs3(int x,int xfa){ for(int y:e[x])if(y^xfa){ g[y]+=g[x]-g[y]-f[y]+x-1-mp[{x,y}]; dfs3(y,x); } } int main(){ ios::sync_with_stdio(0); cin.tie(0); cin>>n; for(int i=1,x,y;i<n;i++){ cin>>x>>y; e[x].push_back(y); e[y].push_back(x); } dfs(4,0); dfs2(4,0,0); dfs3(4,0); for(int i=1;i<=n;i++){ cout<<g[i]+i-1<<" \n"[i==n]; } return 0; } -
0
经典换根 DP + 二维偏序题。
预处理答案, 为 子树下比 小的点的个数, 为 子树下比 小的点的个数。
#include<bits/stdc++.h> using namespace std; #define int long long const int N=2e5+10; vector<int>G[N]; int n; struct BIT { int c[N]; void add(int x,int k){for(;x<=n;x+=x&-x)c[x]+=k;} int get(int x){if(x<0)return 0;int ans=0;for(;x;x-=x&-x)ans+=c[x];return ans;} }tr; int f[N],g[N],h[N],dp[N]; void dfs(int x,int fa) { g[x]-=tr.get(x-1);h[x]-=tr.get(fa-1); tr.add(x,1); for(int y:G[x])if(y!=fa) { dfs(y,x); f[x]+=f[y]; } g[x]+=tr.get(x-1);f[x]+=g[x];h[x]+=tr.get(fa-1); } void dfs2(int x,int fa) { for(int y:G[x])if(y!=fa) { dp[y]=dp[x]+tr.get(y-1)-g[y]-h[y]; dfs2(y,x); } } signed main() { cin>>n; for(int i=1;i<n;i++) { int x,y;cin>>x>>y; G[x].push_back(y); G[y].push_back(x); } dfs(1,0); dp[1]=f[1];dfs2(1,0); for(int i=1;i<=n;i++)cout<<dp[i]<<' ';cout<<'\n'; return 0; }
- 1
信息
- ID
- 8254
- 时间
- 2000ms
- 内存
- 1024MiB
- 难度
- 10
- 标签
- 递交数
- 10
- 已通过
- 3
- 上传者