首页 > 其他分享 >CF1575E 题解

CF1575E 题解

时间:2024-06-06 12:01:14浏览次数:7  
标签:res int 题解 vis maxn siz CF1575E col

CF1575E

思路

点分治,记录当前子树到分治中心的权值和和换车次数。将新子树的答案合并时分类讨论分治中心到子树祖先 \(u\to v\) 的颜色。树状数组维护前缀和。复杂度 \(O(n\log^2 n)\)。

code

int n,k,a[maxn],ans;
int head[maxn],tot;
struct nd{
	int nxt,to,fl;
}e[maxn<<1];
void add(int u,int v,int fl){e[++tot]={head[u],v,fl};head[u]=tot;}
int siz[maxn],w[maxn],rt,sum;
bool vis[maxn];
void getrt(int u,int fa){
	siz[u]=1,w[u]=0;
	for(int i=head[u];i;i=e[i].nxt){
		int v=e[i].to;if(v==fa||vis[v])continue;
		getrt(v,u);
		siz[u]+=siz[v],w[u]=max(w[u],siz[v]);
	}
	w[u]=max(w[u],sum-siz[u]);
	if(w[u]<=sum/2)rt=u;
}
int dis[maxn],num[maxn],col[maxn];
vector<int> id[maxn];
int inc(int u,int v){(u+=v)>=mod&&(u-=mod);return u;}
void dfs(int u,int fa,int tp){
	siz[u]=1;dis[u]=inc(dis[fa],a[u]);
	id[tp].push_back(u);
	for(int i=head[u];i;i=e[i].nxt){
		int v=e[i].to;if(v==fa||vis[v])continue;
		col[v]=e[i].fl;num[v]=num[u]+(col[u]!=col[v]);
		dfs(v,u,tp);siz[u]+=siz[v];
	}
//	cout<<u<<" "<<tp<<" "<<dis[u]<<" "<<num[u]<<"\n";
}
struct bit{
	pii add(pii u,pii v){return {inc(u.fi,v.fi),inc(u.se,v.se)};}
	pii tree[maxn];
	#define lb(x) (x&(-x))
	void upd(int x,int m,pii w){
		while(x<=m)tree[x]=add(tree[x],w),x+=lb(x);
	}
	pii que(int x){
		pii res={0,0};
		while(x>0)res=add(res,tree[x]),x-=lb(x);
		return res;
	}
}t[2];
void sovle(int u){
	vis[u]=1;ans=inc(ans,a[u]);
	siz[u]=1;dis[u]=0;
	for(int i=head[u];i;i=e[i].nxt){
		int v=e[i].to;if(vis[v])continue;
		id[v].clear();num[v]=1;col[v]=e[i].fl;dfs(v,u,v);siz[u]+=siz[v];
	}
	for(int i=1;i<=siz[u];i++)t[0].tree[i]=t[1].tree[i]={0,0};
	for(int i=head[u];i;i=e[i].nxt){
		int v=e[i].to;if(vis[v])continue;
		for(int p:id[v]){
			pii res1=t[e[i].fl].que(min(k-num[p]+1,siz[u])),res2=t[e[i].fl^1].que(min(k-num[p],siz[u]));
			(ans+=(dis[p]+a[u])*(res1.se+res2.se)+res1.fi+res2.fi)%=mod;
			if(num[p]<=k)ans=inc(ans,inc(dis[p],a[u]));
		}
		for(int p:id[v])t[e[i].fl].upd(num[p],siz[u],{dis[p],1});
	}
//	cout<<u<<" "<<ans<<"\n";
	for(int i=head[u];i;i=e[i].nxt){
		int v=e[i].to;if(vis[v])continue;
		sum=siz[v];getrt(v,u);sovle(rt);
	}
}
void work(){
	n=read();k=read()+1;
	for(int i=1;i<=n;i++)a[i]=read();
	for(int i=1;i<n;i++){
		int u=read(),v=read(),fl=read();
		add(u,v,fl),add(v,u,fl);
	}
	sum=n;getrt(1,0);sovle(rt);
	printf("%lld\n",ans);
}

标签:res,int,题解,vis,maxn,siz,CF1575E,col
From: https://www.cnblogs.com/yhddd/p/18234873

相关文章

  • abc355e 题解
    abc355e思路WC2024T3中知道一个技巧:如果知道区间\([l,r]\)的和就连边\(l\tor+1\),那么想推出\([L,R]\)的区间和就要求\(L\)和\(R+1\)联通。按题意把符合要求的边连上,设边权为\(1\)跑bfs,求出\(L\)到\(R+1\)的最短路并记录路径上的点,就可以得到要询问的区间。......
  • CF1007B 题解
    CF1007B思路显然题目要求计数\(u\midA,v\midB,w\midC\)。\(O(n\sqrtn)\)预处理出每个数的所有因数,记为集合\(p_i\)。容斥,记集合\(a,b,c,ab,ac,bc,all\)为\(p_A,p_B,p_C,p_A\capp_B,p_A\capp_A,p_B\capp_C,p_A\capp_B\capp_C\)。可以用bitset维护交集。首先加......
  • 【面试宝藏】MySQL 面试题解析
    MySQL面试题解析1.数据库三大范式是什么?第一范式(1NF):确保每列的原子性,即每列不能再分。第二范式(2NF):在满足1NF的基础上,每个非主属性完全依赖于主键,即消除部分依赖。第三范式(3NF):在满足2NF的基础上,任何非主属性不依赖于其他非主属性,即消除传递依赖。2.MySQL有关权限......
  • 【面试宝藏】Redis 常见面试题解析其二
    Redis高级面试题解析20.说说Redis哈希槽的机制?Redis集群采用哈希槽(HashSlot)机制来分布和管理数据。整个哈希空间被划分为16384个槽,每个键通过CRC16校验后取模映射到一个哈希槽。每个节点负责一部分哈希槽,从而实现数据分片和负载均衡。21.Redis集群的主从复制......
  • P4785 [BalticOI 2016 Day2] 交换 题解
    看到\(i\)和\(\lfloor\frac{i}{2}\rfloor\),考虑一颗二叉树。题目的操作相当于按顺序交换当前节点和左右儿子的权值。假设当前考虑的节点为\(id\),左儿子为\(ls\),右儿子为\(rs\),当前这些点的值分别为\(A,B,C\)。因为\(id\)的位置最靠前,最终又要字典序最小,所以要尽可能......
  • 题解:SP1442 CHAIN - Strange Food Chain
    双倍经验:P2024[NOI2001]食物链思路:一眼鉴定为并查集。观察题目发现有三种状态,考虑使用种类并查集(又称扩展域并查集)。既然有三种状态那么种类并查集自然也要开三倍。CODE:#include<bits/stdc++.h>usingnamespacestd;intfa[150010];intGet_Find(intx){//寻找父节点......
  • P1654 OSU! 题解
    P1654OSU!题解题目链接好题!但不得不说早期洛谷的题解质量是真的差,感觉没有一篇题解是讲的特别清楚的,我看了好久才搞懂。下面是我认为的一种更规范的解题过程。首先,我们设随机变量\(X_i\)表示从\(i\)向左的极长1串的长度,并且对于任意的\(i\),我们要想办法求出\(E(X_i......
  • (第26天)【leetcode题解】226、翻转二叉树 589、N叉树的前序遍历 590、N叉树的后序遍
    目录226、翻转二叉树题目描述思路代码589、N叉树的前序遍历题目描述思路代码590、N叉树的后序遍历题目描述思路代码思考总结226、翻转二叉树题目描述给你一棵二叉树的根节点root,翻转这棵二叉树,并返回其根节点。示例:输入:root=[4,2,7,1,3,6,9]输出:[4,7,2,9,......
  • Codeforces Round 949题解(A、B、C)
    A.TurtleandPiggyArePlayingaGame首先\(p\)选\(2\)的话除得最慢,得的分多。考虑二进制表示,如果\(x=(1000000000)_{bin}\),则每次除以\(2\)都是相当于右移一位,除完之后仍然是\(2\)的倍数,变成\(1\)的步数就是把最高位的\(1\)移动到\(0\)位的步数。因为\(2l\ler\),所以\(l......
  • P8125 [BalticOI 2021 Day2] The short shank 题解
    首先会发现若\(t_i<=T\)的话那么他最终一定会造反。我们只考虑\(t_i>T\)的情况。设\(lst_i\)表示\(i\)左边第一个可以影响(使他造反)到\(i\)的位置,那么我们一定要在\([lst_i,i]\)这个区间中的某一个位置放上床垫才能使\(i\)不造反。这样有一个\(O(nd)\)的dp,但......