【BZOJ 1998】[Hnoi2010]Fsk物品调度 置换群+并查集

置换群的部分水得一比,据说是经典的置换群理论(然而我并不知道这理论是啥).
重点就在于怎么求pos!!!
容易发现这个东西是这样的:每次寻找pos,先在本环里找,找不到再往下一个环里找,直到找到为止……
一开始我想二分或者是set,但是感觉会T,然后想了很久之后想到用并查集:
就是维护每一个被占用的位置的下一个位置,因为这个位置被占用之后就会转向下一个位置,当然下一个位置有在环内部和在下一个环里两种情况,这两种情况都我都是用并查集维护的,但是一定要注意,不要把这两种情况写成一个并查集,这样路径压缩之后会出事,所以要对于这两种情况分别维护两个并查集.

#include <cstdio>
#include <cstring>
#include <algorithm>
typedef long long LL;
const int N=100010;
int n,d,c[N],pos[N],f1[N],f2[N];
bool vis[N];
inline int find1(int x){return f1[x]==x?x:f1[x]=find1(f1[x]);}
inline int find2(int x){return f2[x]==x?x:f2[x]=find2(f2[x]);}
inline int get(int x){
  int ret=find2(find1(x));
  if(find2((ret+d)%n)==ret){
    f1[ret]=(ret+1)%n;
    for(int i=(ret+d)%n;i!=ret;i=(i+d)%n)
      f1[i]=(i+1)%n;
  }else f2[ret]=find2((ret+d)%n);
  return ret;
}
int main(){
  register int i;
  int s,q,p,m,T,j,ans,size;
  bool yeah;
  scanf("%d",&T);
  while(T--){
    scanf("%d%d%d%d%d%d",&n,&s,&q,&p,&m,&d);
    c[0]=0,pos[0]=s,ans=0,d%=n;
    for(i=1;i<n;++i)c[i]=((LL)c[i-1]*q+p)%m;
    for(i=0;i<n;++i)c[i]%=n,vis[i]=false,f1[i]=f2[i]=i;
    get(s);
    for(i=1;i<n;++i)pos[i]=get(c[i]);
    for(i=0;i<n;++i){
      if(vis[i])continue;
      vis[i]=true,yeah=i==0,size=1;
      for(j=pos[i];j!=i;j=pos[j])
        vis[j]=true,++size,yeah=(yeah||(j==0));
      if(size!=1)ans+=size+(yeah?-1:1);
    }
    printf("%d\n",ans);
  }
  return 0;
}

原文地址:https://www.cnblogs.com/TSHugh/p/8516902.html

时间: 2024-09-28 20:11:03

【BZOJ 1998】[Hnoi2010]Fsk物品调度 置换群+并查集的相关文章

【BZOJ】1998: [Hnoi2010]Fsk物品调度

http://www.lydsy.com/JudgeOnline/problem.php?id=1998 题意: 给你6个整数$n,s,q,p,m,d$. 有$n$个位置和$n-1$个盒子,位置编号从$0$开始(盒子编号从$1$开始).一开始第$i$个盒子在第$i$个位置上,$0$号位置是空位.然后有一个$pos$序列,其中$i$位置上放的盒子是$pos_i$(其中$s$位置上必须是空位).问:每次只能将一个盒子移动到空位上(然后这个盒子的位置变成空位),求从初始局面移动到$pos$局面的最少步

bzoj1998: [Hnoi2010]Fsk物品调度

链接......不知道为啥放不动啊. 第一次用手机写bzoj的题,也是第一次用手机写的题解,顺便实现了一下手机上的对拍. 可以用链表+并查集维护一下什么的. 环之间的边是不是不太好路径压缩? 我是直接环内路径压缩,环外不管. 这样应该是会被卡的(d==n???) 可是交上去还是过了. #include<vector> #include<cstdio> #include<cstring> #include<algorithm> #define MN 11000

BZOJ 1050 旅行comf(枚举最小边-并查集)

题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=1050 题意:给出一个带权图.求一条s到t的路径使得这条路径上最大最小边的比值最小? 思路:将边排序.枚举最小边,然后将边一个一个插到并查集里,s和t联通时计算更新答案. struct node { int u,v,w; void get() { RD(u,v,w); } }; int cmp(node a,node b) { return a.w<b.w; } int n,m,s,t;

BZOJ 4199: [Noi2015]品酒大会( 后缀数组 + 并查集 )

求出后缀数组后, 对height排序, 从大到小来处理(r相似必定是0~r-1相似), 并查集维护. 复杂度O(NlogN + Nalpha(N)) ----------------------------------------------------------------------------------- #include<cstdio> #include<cstring> #include<algorithm> using namespace std; ty

BZOJ 1202 [HNOI2005]狡猾的商人(并查集)

[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=1202 [题目大意] 给出一些区间和的数值,问是否存在矛盾 [题解] 用并查集维护前缀和之间的距离,每个节点保存到根节点的数值差, 如果保存的数值差的差与前缀和之差不相等,则矛盾 [代码] #include <cstdio> #include <algorithm> using namespace std; const int N=110; int n,m,f[N],d[

bzoj 1196: [HNOI2006]公路修建问题 二分+并查集

题目链接 1196: [HNOI2006]公路修建问题 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 1576  Solved: 909[Submit][Status][Discuss] Description OI island是一个非常漂亮的岛屿,自开发以来,到这儿来旅游的人很多.然而,由于该岛屿刚刚开发不久,所以那里的交通情况还是很糟糕.所以,OIER Association组织成立了,旨在建立OI island的交通系统. OI isla

【BZOJ 4662】 4662: Snow (线段树+并查集)

4662: Snow Time Limit: 40 Sec  Memory Limit: 256 MBSubmit: 136  Solved: 47 Description 2333年的某一天,临冬突降大雪,主干道已经被雪覆盖不能使用.城 主 囧·雪 决定要对主干道进行一次清扫. 临冬城的主干道可以看为一条数轴.囧·雪 一共找来了n个清理工,第 i个清理工的工作范围为[li,ri],也就是说这个清理工会把[li,ri]这一 段主干道清理干净(当然已经被清理过的部分就被忽略了).当然有可能主 干道

BZOJ 1529 [POI2005]ska Piggy banks(并查集)

[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=1529 [题目大意] 给出一张n个点n条边的有向图,问选取几个点为起点可以遍历全图 [题解] 由于是n条边,因此图为基环森林,选取环上点一定可以到达连通块内所有点, 因此只要统计连通块个数即可. [代码] #include <cstdio> #include <algorithm> using namespace std; const int N=1000100; int

bzoj 4423 [AMPPZ2013]Bytehattan(对偶图,并查集)

[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=4423 [题意] 给定一个平面图,随时删边,并询问删边后两点是否连通.强制在线. [科普] 设有平面图G=(V,E),满足下列条件的图G'= (V',E') 称为图G的对偶图:G的任一面Ri内有且仅有一点Vi':对G的域Ri和Rj的共同边界Ek,画一条边Ek'=(Vi',Vj')且只与Ek交于一点:若Ek完全处于Ri中,则Vi'有一自环Ek',如下图G'是G的对偶图: From her