为了统一描述,下面给出题意——

有$n$只动物,编号为$i$的动物有属性$a_{i,j}$($0\le i<n,0\le j\le 2$)

初始$n$只动物从左到右编号依次为$0,1,...,n-1$,重复以下过程:

(初始$j=0$,假设最左边的两只动物编号依次为$x$和$y$)

1.比较$a_{x,j}$和$a_{y,0}$,将其中较小的那只动物移动到最右边

2.若比较中$a_{x,j}>a_{y,0}$,则令$j$增加1且若$j\ge 3$则游戏结束,否则令$j=1$

输出游戏结束时的$x$以及过程执行的次数,或游戏永远无法结束

$4\le n\le 6\times 10^{3}$,$0\le a_{i,j}\le 10^{9}$,$a_{i,1}<\min(a_{i,0},a_{i,2})$且保证$a_{i,j}$各不相同

以下,我们将题解分为三部分,可能与原题解略有不同

第一部分:颜色的定义即变化

为了方便,我们先手动模拟第一次(即比较$a_{0,0}$和$a_{1,0}$)

对于某一个时刻,我们假设所有动物从左到右编号依次为$id_{0},id_{1},...,id_{n-1}$,给每一只动物一个颜色(红色或非红色),其中$id_{i}$为红色当且仅当$a_{id_{i},0}<a_{id_{i-1},1}$

(特别的,$id_{0}$为“红色”当且仅当$a_{id_{0},0}<a_{id_{n-1},1}$)

首先,考虑$id_{0}$一定非红(手动模拟一次后),证明如下:

考虑$id_{0}$和$d_{n-1}$也就是上一次比较的两只动物且$id_{0}$较大,而若其为红色即$a_{id_{0},0}<a_{id_{n-1},1}$,那么唯一有可能比$id_{n-1}$大的仅有$a_{id_{0},2}$,即比较时$j=2$且胜利后变为$j=3$,游戏已经结束

接下来需要分析每一次颜色的变化,显然将$x$移动到最右边是不会导致动物颜色变化的,只有当$a_{x,j}>a_{y,0}$,也就是$y$移动到最右边时会变化,此时对$j$分类讨论:

1.当$j=1$时,由于$a_{x,1}>a_{y,0}$,根据定义也就是$y$为红色,再令$y'$为$y$下一个位置(即$id_{2}$),颜色会发生变化的也就是$x$、$y$和$y'$这三个位置

对于$x$,其本来是非红色,且$y$为红色可得$a_{y,0}<a_{x,1}$,再根据$a_{i,1}<a_{i,0}$即可得$a_{y,1}<a_{x,0}$,也就是说$x$仍然是非红色

对于$y$,其本来是红色,但根据颜色的信息无法确定其最终的颜色

对于$y'$,对其初始颜色分类讨论:

(1)若其为红色,即$a_{y',0}<a_{y,1}$,不难得到$a_{y',0}<a_{x,1}$,即仍然是红色

(2)若其为非红色,即$a_{y',0}>a_{y,1}$,同样根据颜色的信息无法确定其最终的颜色

2.当$j=2$时,此时若$a_{x,j}>a_{y,0}$即$x$获得胜利,也就没有颜色变化了

综上分析,颜色变化仅在$j=1$且$a_{x,j}>a_{y,0}$($y$移动到最右边)时红色的$y$变为非红色,或非红色的$y'$变为红色(这些变化有可能不发生,但发生的一定是这些变化)

但对于第2种$y'$变为红色,对于下一次,其是红色即$a_{y',0}<a_{x,1}$,同时$a_{x,1}<a_{x,2}$,那么$x$就胜利了

因此,至多只有一次非红色变为红色,根据红色的数量总在$[0,n]$之间,红色变为非红色的次数也至多只有$n+1$次,另外还有至多1次结束操作

对于使得颜色变化或结束的操作,称作特殊操作,数量为$o(n)$

第二部分:操作分组

下面考虑将$n-1$次操作合并为一组操作(手动模拟的第一次操作不计入其中,即$1+(n-1)+(n-1)+...$的形式),显然包含特殊操作的组数也是$o(n)$的

注意到一组操作中,如果初始状态是$id_{i}$,那么第$i$次操作的$y$即为$id_{i}$,且最终放到最后的也就作为下一次的$id\ '_{i}$,最后一轮中未放到最后的是$id\ '_{0}$

如果已经确定某一组内不包含特殊操作,考虑这一组操作的效果——

首先有以下性质:在这一组中的操作,$a_{x,j}>a_{y,0}$当且仅当$y$为红色

$j=1$根据定义是显然的;$j=2$则由于没有结束操作,比较结果必然是$a_{x,2}<a_{y,0}$,也即可推出$a_{x,1}<a_{y,0}$,那么$y$即为非红色,符合性质

且由于没有发生使颜色变化操作,这个$y$的颜色即初始状态中的颜色

由此归纳可得:第$i$次操作时$x$为$[0,i)$之间最后一个非红色的$id_{j}$($id_{0}$为非红色总是存在)且$y=id_{i}$

下面来考虑新的编号序列$id\ '_{i}$,对于$i\ge 1$的$id\ '_{i}$,对第$i$次的$y=id_{i}$分类讨论来确定其值:

1.若$y$为红色,也就是$id\ '_{i}=id_{i}$

2.若$id_{i}$为非红色,那么$id\ '_{i}=x$,也就是其之前第一个非红色的位置

(特别的,$id\ '_{0}$是最后一次操作中未放到最后的,类似归纳过程可得即最后一个非红色的$id_{j}$)

总得来说,最后的$id\ '_{i}$就是在$id_{i}$的基础上,红色位置的不变,非红色的位置向右旋转一圈,之后$j$的值是取决于最后一个位置,即若是红色$j=2$,否则$j=1$

第三部分:快速找到下一个包含特殊操作的组

下面,如果能对于一个$id_{i}$,我们需要知道执行多少组操作(旋转多少次)后可以使得下一组操作中包含特殊操作,再暴力执行这些操作(旋转和下一组)即可

旋转和暴力执行一组操作都是可以做到$o(n)$的,那么关键就是如何$o(n)$找到这个次数

事实上,去除一些细节问题后,比较复杂的主要有两点:

1.对于每一个红色的位置$id_{i}$,找到旋转最少的次数使得其上两个的红色位置$id_{j}$满足$a_{id_{j},1}<a_{id_{i},0}$

2.对于所有相邻的非红色的位置$id_{i}$和$id_{j}$(并不一定有$|i-j|=1$,允许中间有红色),满足$a_{id_{i},2}>a_{id_{j},0}$找到其旋转的最少次数使得其恰好夹着一个红色位置

对于第一点,可以维护一个单调栈,将非红色的位置$a_{id_{j},1}$的后缀最小值找出(很明显既靠后又小的一定优),之后当有红色位置,将其从左边不断弹出比当前位置小的即可

之后由于旋转是环,将序列重复两次即可,另外旋转是非红色的位置,需要维护非红色位置的前缀和

对于第二点,将所有非红色位置提出后,从前往后记录最后一个满足此性质的,当遍历到红色(两个非红色之间有间隙),计算最后一个移动到这个红色的距离即可

略微补充一下细节问题:

1.如果出现相邻的红色,可以直接判定这一轮一定结束;

2.需要先执行若干次,来保证$j$与最后一个位置颜色相同(只执行一次并不一定足够,因为可能有连续两次都包含特殊操作)

总复杂度即$o(n^{2})$,可以通过

  1 #include<bits/stdc++.h>
2 using namespace std;
3 #define N 6005
4 vector<int>v;
5 deque<int>q;
6 int n,id[N],idd[N],tot[N<<1],a[N][3];
7 long long sum;
8 int red(int k){
9 if (!k)return 0;
10 return a[id[k]][0]<a[id[k-1]][1];
11 }
12 int find(){
13 int j=red(n-1)+1,ans=0x3f3f3f3f;
14 if ((j==2)&&(red(1)))return 0;
15 for(int i=1;i<n;i++)
16 if ((red(i-1))&&(red(i)))return 0;
17 tot[0]=1;
18 for(int i=1;i<2*n;i++)tot[i]=tot[i-1]+(!red(i%n));
19 q.clear();
20 for(int i=0;i<2*n;i++)
21 if (red(i%n)){
22 while ((!q.empty())&&(a[id[q.front()%n]][1]<a[id[i%n]][0])){
23 ans=min(ans,tot[i]-tot[q.front()]-1);
24 q.pop_front();
25 }
26 }
27 else{
28 while ((!q.empty())&&(a[id[q.back()%n]][1]>a[id[i%n]][1]))q.pop_back();
29 q.push_back(i);
30 }
31 v.clear();
32 for(int i=0;i<n;i++)
33 if (!red(i))v.push_back(i);
34 if ((j==2)&&(a[id[v[0]]][2]>a[id[v[1]]][0]))return 0;
35 int lst=-1;
36 if (a[id[v.back()]][2]>a[id[v[0]]][0]){
37 lst=0;
38 if (j==2)ans=min(ans,1);
39 }
40 for(int i=1;i<v.size();i++){
41 if (a[id[v[i-1]]][2]>a[id[v[i]]][0]){
42 if (v[i-1]+1<v[i])return 0;
43 lst=v[i];
44 }
45 if ((lst>=0)&&(v[i-1]+1<v[i]))ans=min(ans,v[i]-lst-1);
46 }
47 if (lst>=0){
48 if (j==2)ans=min(ans,n-lst);
49 for(int i=1;i<v.size();i++)
50 if (v[i-1]+1<v[i])ans=min(ans,v[i]+(n-lst)-1);
51 }
52 if (j==2){
53 if (a[id[v[0]]][0]<a[id[v.back()]][1])return 0;
54 for(int i=1;i<v.size();i++)
55 if (a[id[v[i]]][0]<a[id[v[i-1]]][1])ans=min(ans,n-v[i]);
56 }
57 if (ans>n)return -1;
58 return ans;
59 }
60 void turn(int k){
61 sum+=k*(n-1);
62 v.clear();
63 for(int i=0;i<n;i++){
64 if (red(i))idd[i]=id[i];
65 else v.push_back(i);
66 }
67 for(int i=0;i<v.size();i++)idd[v[i]]=id[v[(i+v.size()-k)%v.size()]];
68 memcpy(id,idd,sizeof(id));
69 }
70 int calc(int j){
71 int lst=id[0];
72 for(int i=1;i<n;i++){
73 sum++;
74 if (a[lst][j]>a[id[i]][0]){
75 idd[i]=id[i];
76 if (++j>=3){
77 printf("%d %lld",lst,sum);
78 exit(0);
79 }
80 }
81 else{
82 idd[i]=lst;
83 lst=id[i];
84 j=1;
85 }
86 }
87 idd[0]=lst;
88 memcpy(id,idd,sizeof(id));
89 return j;
90 }
91 int main(){
92 scanf("%d",&n);
93 for(int i=0;i<n;i++)
94 for(int j=0;j<3;j++)scanf("%d",&a[i][j]);
95 for(int i=1;i<n;i++)id[i]=i+1;
96 sum=1;
97 if (a[0][0]<a[1][0]){
98 id[0]=1;
99 id[n-1]=0;
100 }
101 else{
102 id[n-1]=1;
103 id[0]=0;
104 }
105 int j=1;
106 while (1){
107 while (j!=red(n-1)+1)j=calc(j);
108 int i=find();
109 if (i<0){
110 printf("-1 -1");
111 return 0;
112 }
113 turn(i);
114 j=calc(j);
115 }
116 }

[cf1491I]Ruler Of The Zoo的更多相关文章

  1. zookeeper的zoo.cfg的配置

    zookeeper的默认配置文件为zookeeper/conf/zoo_sample.cfg,需要将其修改为zoo.cfg.其中各配置项的含义,解释如下: tickTime:CS通信心跳时间 Zook ...

  2. (转)The Neural Network Zoo

    转自:http://www.asimovinstitute.org/neural-network-zoo/ THE NEURAL NETWORK ZOO POSTED ON SEPTEMBER 14, ...

  3. Mininet建立topology zoo中的拓扑

    以前用Mininet建立拓扑都是在别人的代码上进行需求上的修改,这次从头开始将topology zoo(http://www.topology-zoo.org/)中的拓扑用Mininet建立,不失一般 ...

  4. CSS Ruler 前端工具

    CSS Ruler是一款在线的CSS单位工具. CSS Ruler 彩蛋爆料直击现场 http://katydecorah.com/css-ruler/

  5. zoo.cfg配置

    zookeeper的默认配置文件为zookeeper/conf/zoo_sample.cfg,需要将其修改为zoo.cfg.其中各配置项的含义,解释如下: 1.tickTime:CS通信心跳时间 Zo ...

  6. Codeforces Round #250 (Div. 1) B. The Child and Zoo 并查集

    B. The Child and Zoo Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/contest/438/ ...

  7. cf437D The Child and Zoo

    D. The Child and Zoo time limit per test 2 seconds memory limit per test 256 megabytes input standar ...

  8. CF437D(The Child and Zoo)最小生成树

    题目: D. The Child and Zoo time limit per test 2 seconds memory limit per test 256 megabytes input sta ...

  9. Codeforces 437D The Child and Zoo(贪心+并查集)

    题目链接:Codeforces 437D The Child and Zoo 题目大意:小孩子去參观动物园,动物园分非常多个区,每一个区有若干种动物,拥有的动物种数作为该区的权值.然后有m条路,每条路 ...

随机推荐

  1. gcc、g++、gdb安装

    Windows安装 有闲工夫在Windows上安装g++/gcc/gdb,还不如装个虚拟机安装Linux,在Linux上安装 但是我还是要讲的 首先,需要安装MinGW,MinGW,是Minimali ...

  2. 利用水文分析方法提取山脊线和山谷线(ArcPy实现)

    一.背景 作为地形特征线的山脊线.山谷线对地形.地貌具有一定的控制作用.它们与山顶点.谷底点以及鞍部点等一起构成了地形起伏变化的骨架结构.同时由于山脊线具有分水性,山谷线具有合水性特征,使得它们在地形 ...

  3. 洛谷2120 [ZJOI2007]仓库建设(斜率优化dp)

    感觉和锯木厂那个题很类似的. 其实这个题还那个题唯一的区别就是\(dp\)转移式子中的\(f\)变成了\(g\) qwq不想多说了 直接看我的前一篇题解吧qwq #include<iostrea ...

  4. CF1092F Tree with Maximum Cost(dfs+dp)

    果然我已经菜到被\(div3\)的题虐哭了 qwq 首先看到这个题,一个比较显然的想法就是先从1号点开始\(dfs\)一遍,然后通过一些奇怪的方式,再\(dfs\)一遍得到其他点的贡献. 那么具体应该 ...

  5. Parameter index out of range(1 > number of parameters, which is 0)参数索引超出范围

    今天在写项目的过程中,有一个模块是做多选删除操作,通过servlet获得多选框的value组,然后执行sql操作.如下: 1 @RequestMapping( "/delteCouse.do ...

  6. HttpRunner3.X - 实现参数化驱动

    一.前言 HttpRunner3.X支持三种方式的参数化,参数名称的定义分为两种情况: 独立参数单独进行定义: 多个参数具有关联性的参数需要将其定义在一起,采用短横线(-)进行连接. 数据源指定支持三 ...

  7. 【二食堂】Beta - Scrum Meeting 6

    Scrum Meeting 6 例会时间:5.19 18:30~18:50 进度情况 组员 当前进度 今日任务 李健 1. 实体标注的优化基本已经实现,后端有bug,还没有进行接口调用 issue 2 ...

  8. 猫狗收容所 牛客网 程序员面试金典 C++

    猫狗收容所 牛客网 程序员面试金典 C++ 题目描述 有家动物收容所只收留猫和狗,但有特殊的收养规则,收养人有两种收养方式,第一种为直接收养所有动物中最早进入收容所的,第二种为选择收养的动物类型(猫或 ...

  9. p->next = q, p = q->next, q->next = p->next的区别

  10. 修改记事本PE结构弹计算器Shellcode

    目录 修改记事本PE结构弹计算器Shellcode 0x00 前言 0x01 添加新节 修改节数量 节表位置 添加新节表信息 0x02 添加弹计算器Shellcode 修改代码 0x03 修改入口点 ...