ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

luogu P3345 [ZJOI2015]幻想乡战略游戏

2022-08-26 19:02:21  阅读:146  来源: 互联网

标签:frac rs int luogu Ins ZJOI2015 using P3345 define


题面传送门

本来当成点分树练手题,然后写成动态重心QoT 17了(

首先根据我们分析重心那套\(\frac{n}{2}\)理论我们发现这个东西和边权半毛钱关系没有。

具体的,这道题要求的就是带权重心,而根据普通树重心那套理论,只要一个点的任意子树大小都 \(\leq \frac{n}{2}\)那么这个点就是重心中的一个。

根据QoT的那套理论,一个点的任意子树大小不超过\(\frac{n}{2}\)意味着它的子树大小至少为\(\frac{n}{2}\),则点权dfs序列中最中间的一个点一定在这个重心的子树内,因此可以用树状数组上倍增找到这个中间点,然后再往上倍增找到第一个子树大小大于等于\(\frac{n}{2}\)且最深的点就是重心了。

得到重心以后可以套路的拆掉距离的式子,然后得到两个平凡的东西和一个关于LCA深度的东西,关于LCA深度的东西可以用LNOI2014那题的方法每个被修改点暴力往上差分修改即可。时间复杂度\(O(n\log ^2n)\),常数非常小。

code:

#include<bits/stdc++.h>
#define Gc() getchar() 
#define Me(x,y) memset(x,y,sizeof(x))
#define Mc(x,y) memcpy(x,y,sizeof(x))
#define d(x,y) ((k+1)*(x)+(y))
#define R(n) (rnd()%(n)+1)
#define Pc(x) putchar(x)
#define LB lower_bound
#define UB upper_bound
#define PB push_back
using ll=long long;using db=double;using lb=long db;using ui=unsigned;using ull=unsigned ll;
using namespace std;const int N=100000+5,M=N<<2|5,K=(1<<16)+5,mod=998244353,M1=998244353,M2=1e9+7,Mod=mod-1;const db eps=1e-5;
int n,m,k,x,y,z,Id[N],Ih,Df[N],En[N],Si[N],Sn[N],fa[N],Tp[N],W[N],A[N],f[N][20],lg[N],d[N];ll Ts,Fs;struct Edge{int to,w;};vector<Edge> S[N];
void dfs1(int x,int La){d[x]=d[fa[x]=f[x][0]=La]+1;for(int i=1;f[x][i-1];i++) f[x][i]=f[f[x][i-1]][i-1];Si[x]=1;for(Edge i:S[x]) i.to^La&&(W[i.to]=W[x]+i.w,dfs1(i.to,x),Si[x]+=Si[i.to],Si[Sn[x]]<Si[i.to]&&(Sn[x]=i.to));}
void dfs2(int x,int La){Tp[x]=La;Df[Id[x]=En[x]=++Ih]=x;if(!Sn[x]) return;dfs2(Sn[x],La);for(Edge i:S[x]) i.to^fa[x]&&i.to^Sn[x]&&(dfs2(i.to,i.to),0);En[x]=Ih;}
namespace TA{
	int f[N];void Ins(int x,int y){Fs+=1ll*y*W[Df[x]];Ts+=y;while(x<=n) f[x]+=y,x+=x&-x;}
	int Qry(int x){int Ans=0;while(x) Ans+=f[x],x-=x&-x;return Ans;}
	int Find(){int x=0,Ps=0;for(int i=lg[n];~i;i--) (Ps+f[x+(1<<i)])*2<=Ts&&x+(1<<i)<=n&&(x+=(1<<i),Ps+=f[x]);return Df[x+1];}
}
namespace Tree{
	#define ls v<<1
	#define rs v<<1|1
	ll f[M],g[M],fl[M];void PF(int x,ll w){f[x]+=w*fl[x];g[x]+=w;}void P(int v){g[v]&&(PF(ls,g[v]),PF(rs,g[v]),g[v]=0);}void Up(int v){f[v]=f[ls]+f[rs];}
	void BD(int l=1,int r=n,int v=1){if(l==r) {fl[v]=W[Df[l]]-W[fa[Df[l]]];return;}int m=l+r>>1;BD(l,m,ls);BD(m+1,r,rs);fl[v]=fl[ls]+fl[rs];}
	void Ins(int x,int y,int z,int l=1,int r=n,int v=1){if(x<=l&&r<=y) return PF(v,z);int m=l+r>>1;P(v);x<=m&&(Ins(x,y,z,l,m,ls),0);y>m&&(Ins(x,y,z,m+1,r,rs),0);Up(v);}
	ll Qry(int x,int y,int l=1,int r=n,int v=1){if(x<=l&&r<=y) return f[v];int m=l+r>>1;P(v);return (x<=m?Qry(x,y,l,m,ls):0)+(y>m?Qry(x,y,m+1,r,rs):0);}
	#undef ls
	#undef rs
}
void Ins(int x,int y){TA::Ins(Id[x],y);while(x) Tree::Ins(Id[Tp[x]],Id[x],y),x=fa[Tp[x]];}
void Qry(){int i,x=TA::Find();ll Ans=0;for(i=lg[d[x]];~i;i--) f[x][i]&&(TA::Qry(En[f[x][i]])-TA::Qry(Id[f[x][i]]-1))*2<Ts&&(x=f[x][i]);(TA::Qry(En[x])-TA::Qry(Id[x]-1))*2<Ts&&(x=f[x][0]);/*cerr<<x<<'\n';*/Ans=Fs+W[x]*Ts;while(x) Ans-=2*Tree::Qry(Id[Tp[x]],Id[x]),x=fa[Tp[x]];printf("%lld\n",Ans);}
int main(){
	freopen("1.in","r",stdin);
	int i,j;scanf("%d%d",&n,&m);for(i=1;i<n;i++) scanf("%d%d%d",&x,&y,&z),S[x].PB((Edge){y,z}),S[y].PB((Edge){x,z});dfs1(1,0);dfs2(1,1);for(i=2;i<=n;i++) lg[i]=lg[i/2]+1;
	Tree::BD();while(m--)scanf("%d%d",&x,&y),Ins(x,y),Qry();
}

标签:frac,rs,int,luogu,Ins,ZJOI2015,using,P3345,define
来源: https://www.cnblogs.com/275307894a/p/16628871.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有