首页 > 其他分享 >「题解注释」P7518 [省选联考 2021 A/B 卷] 宝石

「题解注释」P7518 [省选联考 2021 A/B 卷] 宝石

时间:2023-08-13 09:55:24浏览次数:47  
标签:suf 省选 题解 top Dfs son int void 联考

联合省选 2021 宝石 题解 - hezlik 的博客 - 洛谷博客 (luogu.com.cn)

耗时:一晚上+半个上午

代码注释:

#include<bits/stdc++.h>
using namespace std;

const int N=500000,C=21;

int Ri(){
  int x=0,y=1;
  char c=getchar();
  for (;c<'0'||c>'9';c=getchar()) if (c=='-') y=-1;
  for (;c<='9'&&c>='0';c=getchar()) x=x*10+c-'0';
  return x*y;
}

int n,m,sk,a[N+9],pre[N+9],suf[N+9],pos[N+9];
struct side{
  int y,next;
}e[N+9];
int lin[N+9],cs;

void Ins(int x,int y){e[++cs].y=y;e[cs].next=lin[x];lin[x]=cs;}
void Ins2(int x,int y){Ins(x,y);Ins(y,x);}

int fa[N+9],son[N+9],dep[N+9],siz[N+9],top[N+9];
int fir,up1[N+9],up[N+9][C],now[N+9];

void Dfs_ord0(int k,int fat){
  if (now[suf[a[k]]]) up[k][0]=now[suf[a[k]]]; // 上面第一个前驱元素的位置
  for (int i=1;i<C;++i) up[k][i]=up[up[k][i-1]][i-1]; // 倍增处理
  int t=now[a[k]]; // 先存下之前的值
  now[a[k]]=k; // 更新 now 数组
  if (now[fir]) up1[k]=now[fir]; // 记录开始位置
  fa[k]=fat; // 记录父亲
  dep[k]=dep[fat]+1; // 更新深度
  siz[k]=1; // 记录大小
  for (int i=lin[k];i;i=e[i].next)
    if (e[i].y^fat){  
      Dfs_ord0(e[i].y,k);
      siz[k]+=siz[e[i].y];
      if (siz[e[i].y]>siz[son[k]]) son[k]=e[i].y; // (猜测)轻重链剖分
    }
  now[a[k]]=t; // 回溯
}

void Dfs_ord1(int k,int t){ // 处理链顶,轻重链剖分
  top[k]=t;
  if (son[k]) Dfs_ord1(son[k],t);
  for (int i=lin[k];i;i=e[i].next)
    if (e[i].y^fa[k]&&e[i].y^son[k]) Dfs_ord1(e[i].y,e[i].y);
}

int Query_lca(int x,int y){ // 找 lca
  for (;top[x]^top[y];x=fa[top[x]])
    if (dep[top[x]]<dep[top[y]]) swap(x,y);
  return dep[x]<dep[y]?x:y;
}

int cq,ans[N+9];
vector<int>qc[N+9],qid[N+9],q[N+9];

int uni[N+9],sz[N+9],col[N+9],rot[N+9];

int Query_uni(int k){return k==uni[k]?k:Query_uni(uni[k]);} // 找祖先

void Dfs_ans(int k){
  for (int vs=qc[k].size(),i=0;i<vs;++i){
    int c=qc[k][i],t=qid[k][i];
    uni[t]=t; // 并查集祖先
    sz[t]=1; // 并查集大小
    col[t]=c; // 并查集颜色,该颜色为下一个要查找的颜色
    rot[c]?(uni[t]=rot[c],++sz[rot[c]]):rot[c]=t; // 合并
  }
  int x=rot[a[k]]; // 当前颜色的祖先
  rot[a[k]]=0; // 这个颜色已经被收入囊中了
  int c=suf[a[k]],y=rot[c]; // c 后继颜色,y 是 c 的祖先
  if (x){
    if (!y) rot[c]=x,col[x]=c; // 没有下一个颜色的祖先
    else if (sz[x]<sz[y]){ // 启发式合并
      uni[x]=y;
      sz[y]+=sz[x];
    }else{
      uni[y]=rot[c]=x;
      sz[x]+=sz[y];
      col[x]=c; // 此时的颜色为 c
    }
  }
  for (int vs=q[k].size(),i=0;i<vs;++i){
    int t=col[Query_uni(q[k][i])]; // 查询当前询问的问题的祖先的颜色
    ans[q[k][i]]=t?pos[t]-1:sk;
  }
  for (int i=lin[k];i;i=e[i].next)
    if (e[i].y^fa[k]) Dfs_ans(e[i].y);
  if (x){ // 以下全为撤销操作
    if (!y) rot[c]=0,col[x]=a[k];
    else if (rot[c]==y){
      uni[x]=x;
      sz[y]-=sz[x];
    }else{
      uni[y]=rot[c]=y;
      sz[x]-=sz[y];
      col[x]=a[k];
    }
  }
  rot[a[k]]=x;
  for (int vs=qc[k].size(),i=0;i<vs;++i){
    int c=qc[k][i],t=qid[k][i];
    rot[c]==t?rot[c]=0:--sz[uni[t]];
  }
}

int main(){
  n=Ri();m=Ri();sk=Ri();
  for (int i=1;i<=sk;++i) a[i]=Ri();
  fir=a[1];
  for (int i=1;i<=sk;++i){
    pre[a[i]]=a[i-1]; // 记录前驱
    suf[a[i]]=a[i+1]; // 记录后继
    pos[a[i]]=i; // 记录位置
  }
  for (int i = 1; i <= sk; ++ i) {
    cout << pre[a[i]] << ' ' << suf[a[i]] << "col" << '\n';
  }
  for (int i=1;i<=n;++i) a[i]=Ri();
  for (int i=1;i<n;++i){
    int x,y;
    x=Ri();y=Ri();
    Ins2(x,y);
  }
  Dfs_ord0(1,0);
  Dfs_ord1(1,1);
  cq=Ri();
  for (int i=1;i<=cq;++i){
    int x,y,z;
    x=Ri();y=Ri();
    z=Query_lca(x,y);
    if (dep[up1[x]]<=dep[z]){
      qc[z].push_back(fir); // 下一个要找哪个类型的宝石
      qid[z].push_back(i); // 存储问题的编号
      q[y].push_back(i);
    } else{
      int t=up1[x];
      for (int j=C-1;j>=0;--j)
        if (dep[up[t][j]]>dep[z]) t=up[t][j]; // 跳倍增环节
      t=a[t];
      if (suf[t]){ // 当前元素有后继
        qc[z].push_back(suf[t]); // 下一个要找哪个类型的宝石
        qid[z].push_back(i); // 存储问题的编号
        q[y].push_back(i);
      }else ans[i]=m; // 记录答案
    }
  }
  Dfs_ans(1);
  for (int i=1;i<=cq;++i)
    printf("%d\n",ans[i]);
  return 0;
}

标签:suf,省选,题解,top,Dfs,son,int,void,联考
From: https://www.cnblogs.com/yifan0305/p/17626193.html

相关文章

  • CF452C 题解
    洛谷链接&CF链接题目简述有\(m\timesn\)张牌,有\(n\)个种类,每个种类有\(m\)张,现在抽一张放回,再抽一张,求这张牌与第一张抽出的牌种类相同的概率。思路本题是一道结论题,我们来推一下公式。首先需要特判一个点:只有\(1\)张牌,即\(n=m=1\),那么两次抽都会是这张牌,所......
  • acwing 116.飞行员兄弟 (算法竞赛进阶指南 p48 t1 ) 题解
    原题链接https://www.acwing.com/problem/content/description/118/题目描述“飞行员兄弟”这个游戏,需要玩家顺利的打开一个拥有16个把手的冰箱。已知每个把手可以处于以下两种状态之一:打开或关闭。只有当所有把手都打开时,冰箱才会打开。把手可以表示为一个4х4的矩阵,您可以......
  • IDEA/Android Studio的gradle控制台输出中文乱码问题解决
    原文地址:IDEA/AndroidStudio的gradle控制台输出中文乱码问题解决-Stars-One的杂货小窝在项目中,有使用到Gradle自定义脚本,会有些输出日志,但是输出中文就变成乱码了..本篇就介绍下解决方法乱码效果如下图所示步骤我是window系统,不知道其他系统会不会出现这个问题乱......
  • Codeforces Round 874 G题解
    做不动那么多题了,来个GG就是问你一棵树能切成多少个大小为3的链,想了半天,想过dp啥的,但是后来发现这个贪心就好了,可以证明贪心找不到的,其他方法也找不到好久没复健了,这是第一次,感觉以后要多做题才可以#include<bits/stdc++.h>usingnamespacestd;constexprintlimit=(4e......
  • 国标GB28181视频平台LntonGBS(源码版)国标视频云服务平台主子码流都为H.265时,切换出现花
    国标视频云服务LntonGBS平台是基于国标GB28181协议的平台,可实现的视频能力有:实时直播、视频录像、语音对讲、云存储、检索及回放、告警、级联等。平台支持将接入的视频流进行全终端、全平台分发,分发的视频流包括RTSP、RTMP、FLV、HLS、WebRTC等格式。最近有用户反馈,在LntonGBS平台......
  • RTSP流媒体服务器LntonNVR(源码版)安防监控平台开启录像后,录像回看无数据的问题解决方案
    LntonNVR平台通过RTSP/ONVIF协议实现了优秀的视频能力。它可以采集前端接入设备的音视频资源,并将其转码成适用于全平台、全终端分发的视频流格式,包括RTMP、FLV、HLS、WebRTC等格式。这使得LntonNVR平台具备了视频监控直播、云端录像、检索与回看、告警等安防监控功能。平台部署轻快......
  • 联合省选 2023 填数游戏
    这是22年的我:https://www.luogu.com.cn/record/81067862这是23年的我:看我一个流过冲过A性质首先考虑判定。一个经典模型是:如果在\(T_{i,0}\)与\(T_{i,1}\)之间连一条无向边(若\(|T_i|=1\)则认为\(T_{i,1}=T_{i,0}\)),那么题目转化为给每条边定向,使得每个点的入度不超......
  • P7438 更简单的排列计数 题解
    前置芝士:伯努利数等幂求和。其中伯努利数\(B_i\)的生成函数为\(\frac{x}{e^x-1}\)。首先这种逆序对有个套路的dp:令\(f_{i,j}\)表示填了前\(i\)个数,逆序对为\(j\),这时排列的\(val_{\pi}\)的乘积之和。有转移:\(f_{i,j}=\sum\limits_{k=0}^{i-1}f_{i-1,j-k}i^k\),初始......
  • P7092 计数题 题解
    前置题目:P5748集合划分计数。我们令\(Bell_n\)表示将\(n\)个有标号的球划分为若干集合的方案数。且\(Bell_n=n![x^n]e^{e^x-1}\)。首先,当\(k=0\)时,\(\mu(S)=0\),答案为\(0\)。当\(k=1\)时,\(\mu(S)=(-1)^{|S|},\varphi(S)=\prod\limits_{x\inS}(x-1)\)。记\(\pi(S)......
  • [ABC309G] - Ban Permutation 题解
    [ABC309G]-BanPermutation题解题目描述求长为\(N(N\leq100)\)且满足以下条件的排列\(P=(P_1,P_2,...,P_N)\)的个数,模\(998244353\):\(\forall1\leqi\leqN\),\(|P_i-i|\geqX(X\leq5)\)。思路首先拆绝对值,得到:\[P_i\geX+i\veeP_i\leX-i\]数数题除了排列......