玻璃球游戏

【题目描述】

小x的业余生活中,有一项是玩滚玻璃球游戏。
某天,小x想到了一种很无趣的玩法,当然,这种玩法就是为了玩看题的你们。
小x首先建立了一个单向轨道,这个单向轨道可以抽象成一个有向图,每个顶点的出度都是1,也就是由每个点出发,只有一条边连向其他的点。
小x的游戏最初规则是这样的:让玻璃球从某一个点出发,沿着有向边的方向,移动到它的下一个顶点,如果还能移动,就继续移动,直到没有相邻的边,当然会存在在一个环里不停运动的情况。
为了增加难度,小x决定将游戏规则增强,他会提出一系列问题,让你回答:
1) 格式:1 X.查询玻璃球由编号为X的点出发,最终在哪个点停下来,如果能停下来,输出最后的点的编号,如果停不下来,输出”CIKLUS”.
2) 格式:2 X.删除由X出发的那条有向边。

【题解】

这题出的很有意思。

首先是逆向思维,把所有询问存下来,然后倒着往并查集里加边,这样就避免了删边。

然后是并查集的两个优化:

(1)按秩合并

描述:就是在对两个不同子集连接时,按照rank来连,也就是rank低的连在rank高的下面。rank高的做父亲节点。

作用,这样类似维护了一棵树,树是rank高的在上。

(2)路径压缩

描述:假如fa数组已经嵌套了N层,那么传统的做法去找祖先要做N次,当N很大时,这种做法很没效率。

路径压缩代码:

int find(int x)  {return f[x]==x?x:f[x]=find(f[x]);}

十分简洁,十分好记,十分有效。

最后注意,这题来自JZYZOJ1823,要想AC必须汇编开栈。

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<cstdlib>
 5 #include<cmath>
 6 #include<ctime>
 7 #include<algorithm>
 8 using namespace std;
 9 struct node{int flag,x;}qu[300010];
10 int n,q,a[300010],f[300010],vis[300010],ans[300010];
11 inline int read()
12 {
13     int x=0,f=1;  char ch=getchar();
14     while(!isdigit(ch))  {if(ch==‘-‘)  f=-1;  ch=getchar();}
15     while(isdigit(ch))  {x=x*10+ch-‘0‘;  ch=getchar();}
16     return x*f;
17 }
18 int find(int x)  {if(x==-1)return -1;return f[x]==x?x:f[x]=find(f[x]);}
19 int main()
20 {
21     //freopen("cin.in","r",stdin);
22     //freopen("cout.out","w",stdout);
23     int __size__=20<<20;
24     char *__p__=(char*)malloc(__size__)+__size__;
25     __asm__("movl %0, %%esp\n"::"r"(__p__));//汇编开栈
26     n=read();
27     for(int i=1;i<=n;i++)  a[i]=read();
28     q=read();
29     for(int i=1;i<=q;i++)//逆向思维,变删边为加边
30     {
31         qu[i].flag=read();  qu[i].x=read();
32         if(qu[i].flag==2)  vis[qu[i].x]=1;  ans[i]=-2;
33     }
34     for(int i=1;i<=n;i++)  f[i]=i;
35     for(int i=1;i<=n;i++)
36         if(!vis[i]&&a[i])
37         {
38             int y=find(a[i]);
39             if(i==y)  f[a[i]]=-1;
40             f[i]=a[i];
41         }
42     for(int i=q;i;i--)
43     {
44         if(qu[i].flag==1)  ans[i]=find(qu[i].x);
45         else
46         {
47             int x=qu[i].x;
48             int y=find(a[x]);
49             if(x==y)  f[a[x]]=-1;
50             f[x]=a[x];
51         }
52     }
53     for(int i=1;i<=q;i++)
54         if(ans[i]==-1)  printf("CIKLUS\n");
55         else if(ans[i]!=-2)  printf("%d\n",ans[i]);
56     return 0;
57 }
时间: 2024-08-29 09:29:21

玻璃球游戏的相关文章

NOJ 1118 玻璃球 【深蓝】[状态压缩DP]

玻璃球 [深蓝] 时间限制(普通/Java) : 10000 MS/ 30000 MS 运行内存限制 : 65536 KByte总提交 : 57            测试通过 : 11 比赛描述 玩过玻璃球游戏吗?sed同学小学没有毕业之前玩过,他常常用一个直径为d的圆柱管来装玻璃球,已知每个玻璃球是半径为 r1, r2, . . . , rn的球体,他当时一直有一个疑问:装这些玻璃球最少需要多长的圆柱管.现请你帮他解决这个问题. 假设玻璃球半径充分大,以至于管中不存在三个可以同时相互接触的玻

20170913自制猜数字游戏

/* 猜数字:系统随机生成一个四位数,请根据下列判断猜出来 A:数值正确,位置正确 B:数值正确,位置不正确 C:数值不正确 */ #include<stdio.h> #include<time.h> #include<stdlib.h> #pragma warning (disable:4996) #define pUCharHead unsigned char * //以数组形式返回n个无重复的随机数,范围可指定[min,max] pUCharHead GenNoR

洛谷P1199 三国游戏

题目描述 小涵很喜欢电脑游戏,这些天他正在玩一个叫做<三国>的游戏. 在游戏中,小涵和计算机各执一方,组建各自的军队进行对战.游戏中共有 N 位武将(N为偶数且不小于 4),任意两个武将之间有一个"默契值",表示若此两位武将作为一对组合作战时,该组合的威力有多大.游戏开始前,所有武将都是自由的(称为自由武将,一旦某个自由武将被选中作为某方军队的一员,那么他就不再是自由武将了),换句话说,所谓的自由武将不属于任何一方. 游戏开始,小涵和计算机要从自由武将中挑选武将组成自己的军

游戏开发 系统app开发游戏定制开发找谁

梦幻珍珠港理财拆分游戏系统软件开发怎么做?找[江生:185-2911-8412 微电]. 梦幻珍珠港拆分游戏平台开发.梦幻珍珠港理财全网模式开发.梦幻珍珠港收益模式介绍开发. 梦幻珍珠港拆分游戏系统源码搭建平台!!我们是软件开发,玩家勿扰!非平台客服,玩家勿扰!] 游戏规则: 一.开发新会员要从您的库房扣除3 03颗珍珠,体系扣除5颗珍珠,新会员有298颗珍珠. 二.推荐老友,推荐人能够得到第一代会员的2%,第二代会员的1%,第三代会员的0.5%,一代的收益就是5.96颗珍珠奖赏(可转换为等量可

游戏服务器开发需要学习的技术

一,游戏服务器编程语言的选择 所谓的游戏服务器编程语言其实有很多,基本上任何一种语言都可以作为游戏服务器的编程语言.这需要根据自己游戏的类型和要求加以选择.比如C++,Java ,Erlang,go等等.目前我用过的只有C++和Java.但是以Java为主.所以接下来就以自己的经验,谈谈以Java为核心的游戏服务器开发技术体系. Java目前作为游戏服务器开发语言已经很是普遍.但是大多数是作为页游或手游的服务器,而端游戏一般选择C++,因为端游对服务器的性能要求相对比较高一些.两种语言各有利弊.

赛码网算法: 格子游戏

格子游戏 题目描述 有n个格子,从左到右放成一排,编号为1-n.共有m次操作,有3种操作类型:1.修改一个格子的权值,2.求连续一段格子权值和,3.求连续一段格子的最大值.对于每个2.3操作输出你所求出的结果. 输入输入第一行两个整数,n表示格子个数,m表示操作次数,n和m中间用空格隔开:接下来输入n行,每行一个整数表示一个格子的权值接下来输入m行,每行有三个整数,中间用空格隔开:第一个是选择的操作类型1-3,第二和第三个整数是操作格子的编号.样例输入3 37892 1 33 1 32 1 2输

【BZOJ4945】[Noi2017]游戏 2-SAT

[BZOJ4945][Noi2017]游戏 题目描述 题解:2-SAT学艺不精啊! 这题一打眼看上去是个3-SAT?哎?3-SAT不是NPC吗?哎?这题x怎么只有8个?暴力走起! 因为x要么不是A要么不是B,所以直接2^8枚举所有x就行了.然后就变成了一个2-SAT问题.假设有两场游戏1,2,分别可以使用的地图为A1,A2,B1,B2,如果有一个限制是1 A 2 A,那么选A1就必须选A2,然后我这个沙茶就开开心心的拿了55分. 为什么不对?我建出来的图显然不对偶啊!考虑逆否命题,选A1就必须选

“盛大游戏杯”第15届上海大学程序设计联赛夏季赛暨上海高校金马五校赛 B

<神无月>作为盛大游戏2017年的全新原创大作,其开发团队在自研实力强大的传世工作室基础之上,还有美树本晴彦等日本一线知名画师及日本游戏音乐大师崎元仁加盟参与制作.目前正在不限号内测中,有很多玩家进入到神无月的世界中. 在神无月中,有着玩家之间切磋的排位赛,其段位主要分为五大段位,从低到高依次为:新兵.菁英.战将.统帅.王者.每个玩家只有从新兵段位慢慢努力,一点点晋级才能到达王者段位.成为一个王者是每一个玩家的追求和心愿. 假设神无月的段位系统如下: 从低到高的段位依次简记为:D.C.B.A.

P1070 道路游戏

题目描述 小新正在玩一个简单的电脑游戏. 游戏中有一条环形马路,马路上有 n 个机器人工厂,两个相邻机器人工厂之间由一小段马路连接.小新以某个机器人工厂为起点,按顺时针顺序依次将这 n 个机器人工厂编号为1~n,因为马路是环形的,所以第 n 个机器人工厂和第 1 个机器人工厂是由一段马路连接在一起的.小新将连接机器人工厂的这 n 段马路也编号为 1~n,并规定第 i 段马路连接第 i 个机器人工厂和第 i+1 个机器人工厂(1≤i≤n-1),第 n 段马路连接第 n 个机器人工厂和第 1个机器人