社区讨论
玄关超时一点点求卡常
P9706「TFOI R1」Ride the Wind and Waves参与者 2已保存回复 2
讨论操作
快速查看讨论及其快照的属性,并进行相关操作。
- 当前回复
- 2 条
- 当前快照
- 1 份
- 快照标识符
- @mi0v9y86
- 此快照首次捕获于
- 2025/11/16 06:37 3 个月前
- 此快照最后确认于
- 2025/11/17 09:11 3 个月前
CPP
#include<bits/stdc++.h>
#define ll long long
#define R register
#define F(i,a,b) for(int i = (a);i<=(b);i++)
using namespace std;
inline ll read(){R ll x=0,t=1;R char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-') t=-1;ch=getchar();}while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}return x*t;}
const int N=1e6+10;
int n,k;
struct edge
{
int u,v;
ll w;
}e[N];
vector<int>g[N],b[N];
vector<ll>w[N];
inline void add(int u,int v,ll wo)
{
g[u].push_back(v);
w[u].push_back(wo);
return;
}
int fl[N],fa[N];
ll val1[N];
ll dep[N];
int flag,to[N],ww[N];
ll ans[N];
bool vis[N];
void dfs(int u,int Fa)
{
// cout << u << " " << Fa << '\n';
vis[u]=1;
for(R int i = 0;i<g[u].size();i++){
int v=g[u][i];
if(v==Fa) continue;
if(!vis[v]){
vis[v]=1;
fa[v]=u;
dfs(v,u);
}
else if(!flag){
flag=1;
while(u!=v){
// cout << u << "#" << v <<'\n';
fl[u]=1;
u=fa[u];
}
fl[v]=1;
// return;
}
}
}
ll val[N];
ll dis[N];
void dfs1(int u,int Fa,int rt)
{
fa[u]=Fa;
for(R int i = 0;i<g[u].size();i++){
int v=g[u][i];
if(fl[v] || v==Fa) continue;
b[rt].push_back(v);
dis[v]=dis[u]+w[u][i];
dep[v]=dep[u]+1;
if(dep[v]>=k) val[rt]+=dis[v];
dfs1(v,u,rt);
}
return;
}
ll sumup[N],siz[N],cf1[N],cf2[N];
inline int Get(int x,int dep)
{
int rsum=dep;
while(rsum--){
if(fl[x] || x==0){
return -1;
}
x=fa[x];
}
return x;
}
void dfs2(int u,int fa)
{
siz[u]=1;
for(R int i = 0;i<g[u].size();i++){
int v=g[u][i];
if(v==fa || fl[v]) continue;
dfs2(v,u);
siz[u]+=siz[v];
sumup[u]+=sumup[v]+siz[v]*w[u][i];
}
int anc2=Get(u,k-1);
if(anc2==-1) return;
int anc=Get(anc2,1);
if(anc==-1) return;
int rsum=siz[u]*(dis[u]-dis[anc])+sumup[u];//u子树内的所有点到anc的距离和
cf1[anc]+=rsum,cf1[anc2]-=rsum;//差分
cf2[anc]+=rsum*dis[anc],cf2[anc2]-=rsum*dis[anc];
}
void dfsdown(int u,int fa)
{
for(R int i = 0;i<g[u].size();i++){
int v=g[u][i];
if(v==fa || fl[v]) continue;
cf1[v]+=cf1[u],cf2[v]+=cf2[u];
dfsdown(v,u);
}
ans[u]+=dis[u]*cf1[u]-cf2[u];
// if(cf1[u]) assert(0);
// if(cf2[u]) assert(0);
// if(ans[u]) assert(0);
}
signed main()
{
n=read(),k=read();
F(i,1,n){
e[i].u=read(),e[i].v=read(),e[i].w=read();
add(e[i].u,e[i].v,e[i].w);
add(e[i].v,e[i].u,e[i].w);
}
dfs(1,0);
// for(int i = 1;i<=n;i++){
// if(fl[i]) cout << i << " ";
// }
//cout << '\n';
memset(dep,0,sizeof dep);
ll sumv=0;
F(i,1,n){
if(fl[i]){
b[i].push_back(i);
dfs1(i,0,i);
sumv+=val[i];
dfs2(i,0);
dfsdown(i,0);
// cout << i << " " << val[i] << '\n';
}
}
int st=0;
ll sumw=0;
F(i,1,n){
if(fl[e[i].u] && fl[e[i].v]){
to[e[i].u]=e[i].v;
ww[e[i].u]=e[i].w;
sumw+=e[i].w;
}
}
F(i,1,n){
if(fl[i]){
st=i;
break;
}
}
int now=st;
ll noww=0,nowv=0,fll=0;
while(1){
if(now==st){
if(!fll) fll=1;
else break;
}
noww+=ww[now];
if(to[now]!=st) nowv+=noww*val[to[now]];
// cout<< now << " " << to[now] << " " << noww << " " << nowv << '\n';
now=to[now];
}
now=st;
fll=0;
while(1){
if(now==st){
if(!fll) fll=1;
else break;
}
for(int v:b[now]){
// cout << v << '\n';
ans[v]+=dis[v]*(sumv-val[now]);
ans[v]+=nowv;
}
nowv=nowv-ww[now]*(sumv-val[now]);
nowv=nowv+val[now]*(sumw-ww[now]);
now=to[now];
}
F(i,1,n) printf("%lld\n",ans[i]);
return 0;
}
/*
8 1
1 4 3
2 1 2
3 1 6
4 3 4
5 2 4
6 4 1
7 5 2
8 5 2
*/
回复
共 2 条回复,欢迎继续交流。
正在加载回复...