首页 > 其他分享 >P7215 [JOISC2020] 首都]

P7215 [JOISC2020] 首都]

时间:2024-08-01 09:50:20浏览次数:15  
标签:颜色 int siz 分治 JOISC2020 节点 maxsiz P7215 首都

P7215 [JOISC2020] 首都

考虑对于颜色 \(c_i\) , 若在此颜色集合内所有节点之间的路径上出现了其他颜色 ( 如 \(c_j\) ) , 那我们则不得不将这两种颜色合并在一起,操作数加一。

即对于颜色 \(c_i\) ,若设其为首都,其答案 ( 操作数 ) 为所有颜色为 \(c_i\) 的节点之间的路径上的颜色种类数减一 ( 因为颜色种类数包括 \(c_i\) 自身 ) 。则 \(ans\) 为所有颜色的答案的最小值。

考虑朴素的做法。具体地,对于颜色 \(c_i\) , 操作数初始为 0,以此颜色集合中的一个点为根,将所有颜色为 \(c_i\) 的点放入队列,从队内弹出一个点 \(u\) ,若其父亲 \(f_u\) 的颜色此前未标记 (设其颜色为 \(c_j\) ),则再将所有颜色为 \(c_j\) 的点放入队列。不断重复,直到没有产生新的颜色节点为止。每次复杂度为 \(O(n)\),总复杂度为 \(O(n^2)\)。

用点分治维护此操作,以当前的分治中心为根在其子树内进行相同操作,但是当在统计过程中出现的颜色节点在当前分治中心的子树外,则直接退出,本次答案统计作废。因为若这个颜色节点在当前子树外,则它与当前分治中心的路径上必会经过上一级分治节点 ( 即上一级分治中心的答案也会被统计在当前答案内 ) ,相当于上一级分治节点的颜色序列必包含在当前的分治中心的颜色序列中,即当前的答案只会相同或更劣。这一步操作较为关键,它能较大的优化统计答案的效率。

可以发现,虽然每次的统计仍然是 \(O(n)\) 的,但是在点分治下递归枚举的次数降到了 \(O(logn)\)。因此总的时间复杂度为 \(O(nlogn)\)。可以通过本题。

备注:有关点分治时间复杂度的证明:

  • 分治中心为当前子树的重心
  • 根据重心的性质,每进行一次分治操作,问题规模 ( 子树大小 ) 就会减小一半。说明点分治的递归次数为 \(O(logn)\) 级别。

另:点分治

本题代码如下

#include<bits/stdc++.h>
using namespace std;
const int N=2e5+10;
int n,k;
int u,v;
int ans=1e9+10,res;
vector < int >edge[N],col[N];
int c[N];
int siz[N],f[N];
int rt;
queue<int>q;
int tag[N],c_tag[N],vis[N];
int stc[N],tp;
int maxsiz[N];
void getrt(int t,int fa,int _siz){
	siz[t]=1,maxsiz[t]=0;;
	for(auto v : edge[t]){
		if(v==fa || vis[v])continue;
		getrt(v,t,_siz);
		siz[t]+=siz[v];
    maxsiz[t]=max(maxsiz[t],siz[v]);
	}
  maxsiz[t]=max(maxsiz[t],_siz-siz[t]);
  if(maxsiz[t]<maxsiz[rt])rt=t;
}

bool is_push(vector<int> &cl){
  for(int i=0;i<cl.size();i++){
    if(!tag[cl[i]])return 1; //若统计范围在当前子树外,避免本次统计
    q.push(cl[i]);
  }
  res++;
  return 0;
}
void dfs(int t,int fa){
  f[t]=fa;
  for(auto v:edge[t]){
    if(v==fa || vis[v])continue;
    dfs(v,t);
  }
}
void calc(int t){
  res=0;
  while(!q.empty())q.pop();
  c_tag[c[t]]=1;
  if(is_push(col[c[t]]))return ;
  dfs(t,t);
  while(!q.empty()){
    int u=q.front();
    q.pop();
    if(!c_tag[c[f[u]]]){
      c_tag[c[f[u]]]=1;
      if(is_push(col[c[f[u]]]))return ;
    }
  }
  ans=min(ans,res);
}
void sign(int t,int fa){ //确定当前分治中心的子树范围
  stc[++tp]=t,tag[t]=1;
  for(auto v:edge[t]){
    if(v==fa || vis[v])continue;
    sign(v,t);
  }
}
void solve(int t){
  vis[t]=1,sign(t,t);
  calc(t);
  while(tp){
    tag[stc[tp]]=c_tag[c[stc[tp]]]=0;
    tp--;
  }
  for(auto v:edge[t]){
    if(vis[v])continue;
    rt=0;
    getrt(v,t,siz[v]);
    solve(rt);
  }
}
int main(){
  ios::sync_with_stdio(false);
  cin.tie(0);
  cout.tie(0);
  cin>>n>>k;
  for(int i=1;i<n;i++){
    cin>>u>>v;
    edge[u].push_back(v);
    edge[v].push_back(u);
  }
  for(int i=1;i<=n;i++){
    cin>>c[i];
    col[c[i]].push_back(i);
  }
  rt=0;
  maxsiz[rt]=n;
  getrt(1,1,n);
  solve(rt);
  cout<<ans-1<<'\n';//ans为连通块内最少颜色种类数
  return 0;
}

标签:颜色,int,siz,分治,JOISC2020,节点,maxsiz,P7215,首都
From: https://www.cnblogs.com/-y-0-x-0-h-/p/18334966

相关文章

  • P7219 [JOISC2020] 星座 3 题解
    会发现题目的坐标其实是平面直角坐标系。我们按\(y\)坐标从小到大考虑所有的星星,假设当前考虑到了星星\(i\)。我们先计算出之前所有能够影响到\(i\)的星星的代价和为\(cost\)(可以用树状数组维护)。然后分类讨论。若\(c_i\lecost\),那么肯定直接将\(i\)直接涂黑,因为它更......
  • P7219 [JOISC2020] 星座 3【笛卡尔树+整体dp】
    P7219[JOISC2020]星座3笛卡尔树+整体dp(线段树合并维护dp)考虑转化题意,不存在矩形为星座,即对于每个极大矩形中都只有一颗星星。而观察题目的方格,对于两个位置是否能够成为一个矩形,只和两个位置的区间最大值(小白船的位置)有关①。图中的红蓝矩形即为两个极大矩形。将删除星......
  • JOISC2020
    [JOISC2020]最古の遺跡3好难的题。首先考虑给出\(h\)怎么求\(A\),设\(h'_i\)为\(i\)位置剩下的高度,没了就\(=0\)。方便起见,我们把原序列翻转一下,那么题目的操作就是,每种高度的最靠左的位置不变。我们从左到右依次求解,先令\(h'_i=h_i\),若\(h'_i\)在\(j<i\)的\(......
  • [JOISC2020] 扫除
    现在Bitaro准备用扫帚打扫房间。我们认为扫帚是放置在房间里的一条线段,并且将这条线段的长度称为扫帚的宽度。由于Bitaro很有条理,所以他只会用以下的两种方式打扫房间:Bitaro将扫帚平行于\(y\)轴放置,一端位于原点。然后他会垂直向右移动扫帚,直到不能移动为止。如果扫帚的......
  • [JOISC2020] 最古の遺跡 3
    [JOISC2020]最古の遺跡3题目背景JOI教授是一名研究IOI王国的历史学家。题目描述他发现了一行古代石柱的废墟及一份古代文献。古代文献上的记载如下:刚建造完成的时候,有\(2\timesN\)个石柱,对于\(1\lek\leN\)均有两个石柱高度为\(k\),同时记第\(i\)个石柱的高度......
  • JOISC2020题解
    \(\text{ByDaiRuiChen007}\)ContestLinkA.Building4ProblemLink题目大意给\(2n\)个数对\((a_i,b_i)\),构造一个非降序列\(c_i\)满足\(\forall1\lei\len,c_i\in\{a_i,b_i\}\),且\(c_i=a_i\)的位置恰好有\(n\)个。数据范围:\(n\le5\times10^5\)。思路......
  • 云行 | 云启新境 智赋未来,天翼云智绘数字首都新图景!
    2023年12月12日,以“云启新境,智赋未来”为主题的天翼云中国行·北京站活动在北京圆满举行,会上中国信息通信研究院和天翼云科技有限公司联合发布央国企上云白皮书,为推动政府企事业单位上云用云制定标准,为各单位生产方式、业务形态、商业模式的数字化创新转型持续助力。国wu院国有资产......
  • 力扣2477. 到达首都的最少油耗(dfs+贪心)
    给你一棵 n 个节点的树(一个无向、连通、无环图),每个节点表示一个城市,编号从 0 到 n-1 ,且恰好有 n-1 条路。0 是首都。给你一个二维整数数组 roads ,其中 roads[i]=[ai,bi] ,表示城市 ai 和 bi 之间有一条 双向路 。每个城市里有一个代表,他们都要去首都参......
  • P7215首都
    2023-09-14题目P7215[JOISC2020]首都难度&重要性(1~10):8题目来源luogu题目算法点分治解题思路一个显然的\(O(n^2)\)的暴力思路。因为这是一颗树,我们就每一次将城镇\(1\simn\)定为根节点,将这个城镇的所属城市定为首都,而要求首都的其他城镇到根节点的路径上只有首......
  • 题解 P7215
    点分治。考虑当前的分治重心的城市被完全联通。这可以用队列接解决。每次放入一种城市,就把那些城镇的父亲加入队列,如果存在城镇不在当前分治重心的联通块内,那么说明必定存在另一个分治重心能算到它,直接退出即可。剩下的和模板没有任何区别。复杂度\(O(n\logn)\)。code:#in......