HDU 3487 Play with Chain | Splay

Play with Chain

Time Limit: 6000/2000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)

【Problem Description】
YaoYao is fond of playing his chains. He has a chain containing n diamonds on it. Diamonds are numbered from 1 to n. At first, the diamonds on the chain is a sequence: 1, 2, 3, …, n. He will perform two types of operations:
CUT a b c: He will first cut down the chain from the ath diamond to the bth diamond. And then insert it after the cth diamond on the remaining chain. For example, if n=8, the chain is: 1 2 3 4 5 6 7 8; We perform “CUT 3 5 4”, Then we first cut down 3 4 5, and the remaining chain would be: 1 2 6 7 8. Then we insert “3 4 5” into the chain before 5th diamond, the chain turns out to be: 1 2 6 7 3 4 5 8.
FLIP a b: We first cut down the chain from the ath diamond to the bth diamond. Then reverse the chain and put them back to the original position. For example, if we perform “FLIP 2 6” on the chain: 1 2 6 7 3 4 5 8. The chain will turn out to be: 1 4 3 7 6 2 5 8
He wants to know what the chain looks like after perform m operations. Could you help him?
【Input】
There will be multiple test cases in a test data. For each test case, the first line contains two numbers: n and m (1≤n, m≤3*100000), indicating the total number of diamonds on the chain and the number of operations respectively. Then m lines follow, each line contains one operation. The command is like this: CUT a b c   // Means a CUT operation, 1 ≤ a ≤ b ≤ n, 0≤ c ≤ n-(b-a+1). FLIP a b    // Means a FLIP operation, 1 ≤ a < b ≤ n. The input ends up with two negative numbers, which should not be processed as a case.
【Output】
For each test case, you should print a line with n numbers. The ith number is the number of the ith diamond on the chain.
【Sample Input】
8 2 
CUT 3 5 4 
FLIP 2 6 
-1 -1

【Sample Output】

1 4 3 7 6 2 5 8

 

【题意】

给出一列数,然后对整个数列执行两种操作:切下一段插入到另外的位置,或者把其中的一整段整个翻转一下。

求经过一系列操作之后,数列最后的样子。

 

【分析】

数据范围最高能够到达3e5那么大,因此算法至少要是O(nlogn)复杂度以下才可能达到要求。

考虑采用Splay解决(这样的题目只能用这种动态维护的树结构不是么?)

 

初始先建树,把1~n加入Splay树。由于数列在后面是要被打乱顺序的,Splay二叉平衡树的性质只有在初始的时候是被保持的,之后是靠size,即每个点在中序遍历中的位置来维护。最后输出数列则只需要中序遍历一遍即可。

切割操作:若要切下a~b段,则把第a-1个结点移到根,把第b+1个结点移到根以下(即跟的右子树),则整个a~b段就落在b+1的左子树上,切出来。插入到c的时候,将c移到根,c+1移到根的右子树,则切出来的插入到c+1的左子树即可

翻转操作:用上面相同的方法把a~b整合到一棵子树上,然后可以参考线段树标记的方法,通过标记来完成访问结点的翻转等操作。

具体可以在纸上模拟一下......

 

【教训】

教训还是比较惨痛的...卡在这道题上好久了。

首先是输入输出以后要特别注意结尾方式,两个负数结尾还是两个-1结尾

把各种可能出现的不同情况考虑完整

 

  1 /* ***********************************************
  2 MYID    : Chen Fan
  3 LANG    : G++
  4 PROG    : HDU3487
  5 ************************************************ */
  6 
  7 #include <iostream>
  8 #include <cstdio>
  9 #include <cstring>
 10 #include <algorithm>
 11 
 12 using namespace std;
 13 
 14 #define MAXN 300010
 15 
 16 int sons[MAXN][2];
 17 int father[MAXN],size[MAXN],data[MAXN],list[MAXN];
 18 bool flag[MAXN];
 19 int spt=0,spttail=0;
 20 
 21 void down(int x)
 22 {
 23     if (flag[x])
 24     {
 25         flag[x]=0;
 26         swap(sons[x][0],sons[x][1]);
 27         flag[sons[x][0]]^=1;
 28         flag[sons[x][1]]^=1;
 29     }
 30 }
 31 
 32 void rotate(int x,int w) //rotate(node,0/1)
 33 {
 34     int y=father[x];
 35     down(y);down(x);
 36     sons[y][!w]=sons[x][w];
 37     if (sons[x][w]) father[sons[x][w]]=y;
 38 
 39     father[x]=father[y];
 40     if (father[y]) sons[father[y]][y==sons[father[y]][1]]=x;
 41 
 42     sons[x][w]=y;
 43     father[y]=x;
 44 
 45     size[x]=size[y];
 46     size[y]=size[sons[y][0]]+size[sons[y][1]]+1;
 47 }
 48 
 49 void splay(int x,int y) //splay(node,position)
 50 {
 51     down(x);
 52     while(father[x]!=y)
 53     {
 54         if (father[father[x]]==y) rotate(x,x==sons[father[x]][0]);
 55         else 
 56         {
 57             int t=father[x];
 58             int w=(sons[father[t]][0]==t);
 59             if (sons[t][w]==x)
 60             {
 61                 rotate(x,!w);
 62                 rotate(x,w);
 63             } else 
 64             {
 65                 rotate(t,w);
 66                 rotate(x,w);
 67             }
 68         }
 69     }
 70     if (!y) spt=x;
 71 }
 72 
 73 void select(int x,int v,int p) //select(root,k,position)
 74 {
 75     down(x);
 76     while(v!=size[sons[x][0]]+1)
 77     {
 78         if (v<=size[sons[x][0]]) 
 79         {
 80             x=sons[x][0];
 81             down(x);
 82         }
 83         else 
 84         {
 85             v-=size[sons[x][0]]+1;
 86             x=sons[x][1];
 87             down(x);
 88         }
 89     }
 90     splay(x,p);
 91 }
 92 
 93 bool done=false;
 94 
 95 void outp(int x)
 96 {
 97     down(x);
 98     if (sons[x][0]) outp(sons[x][0]);
 99     if (done) printf(" ");
100     done=true;
101     printf("%d",data[x]);
102     if (sons[x][1]) outp(sons[x][1]);
103 }
104 
105 void maketree(int l,int r)
106 {
107     spttail++;
108     int now=spttail,w=(l+r)/2,ls=0,rs=0;
109     data[now]=w;
110     flag[now]=false;
111     sons[now][0]=0;
112     sons[now][1]=0;
113     
114     if (l<=w-1)
115     {
116         ls=spttail+1;
117         sons[now][0]=ls;
118         father[ls]=now;
119         maketree(l,w-1);
120     }
121     if (w+1<=r)
122     {
123         rs=spttail+1;
124         sons[now][1]=rs;
125         father[rs]=now;
126         maketree(w+1,r);
127     }
128 
129     size[now]=size[ls]+size[rs]+1;
130 }
131 
132 int main()
133 {
134     freopen("3487.txt","r",stdin);
135     
136     int n,m;
137     scanf("%d%d",&n,&m);
138     while(!(n<0&&m<0))
139     {
140         spt=1;
141         spttail=0;
142         father[1]=0;
143         maketree(1,n);
144 
145         for (int i=1;i<=m;i++)
146         {
147             char s[10];
148             scanf("%s",&s);
149             if (s[0]=='C')
150             {
151                 int a,b,c,temp;
152                 scanf("%d%d%d",&a,&b,&c);
153 
154                 if (a>1)
155                 {
156                     select(spt,a-1,0);
157                     if (b<n)
158                     {
159                         select(spt,b+1,spt);
160                         temp=sons[sons[spt][1]][0];
161                         sons[sons[spt][1]][0]=0;
162                         size[spt]-=size[temp];
163                         size[sons[spt][1]]-=size[temp];
164                     } else 
165                     {
166                         temp=sons[spt][1];
167                         sons[spt][1]=0;
168                         size[spt]-=size[temp];
169                     }
170                 } else 
171                 {
172                     if (b<n)
173                     {
174                         select(spt,b+1,0);
175                         temp=sons[spt][0];
176                         sons[spt][0]=0;
177                         size[spt]-=size[temp];
178                     } else temp=spt;
179                 }
180 
181                 if (c>0)
182                 {
183                     select(spt,c,0);
184                     if (c==size[spt])
185                     {
186                         sons[spt][1]=temp;
187                         father[temp]=spt;
188                         size[spt]+=size[temp];
189                     } else
190                     {
191                         select(spt,c+1,spt);
192                         sons[sons[spt][1]][0]=temp;
193                         father[temp]=sons[spt][1];
194                         size[spt]+=size[temp];
195                         size[sons[spt][1]]+=size[temp];
196                     }
197                 } else 
198                 {
199                     if (spt!=temp)
200                     {
201                         select(spt,1,0);
202                         sons[spt][0]=temp;
203                         father[temp]=spt;
204                         size[spt]+=size[temp];
205                     }
206                 }  
207             } else 
208             {
209                 int a,b,temp;
210                 scanf("%d%d",&a,&b);
211                 if (a>1)
212                 {
213                     select(spt,a-1,0);
214                     if (b<n)
215                     {
216                         select(spt,b+1,spt);
217                         temp=sons[sons[spt][1]][0];
218                     } else 
219                     {
220                         temp=sons[spt][1];
221                     }
222                 } else 
223                 {
224                     if (b<n)
225                     {
226                         select(spt,b+1,0);
227                         temp=sons[spt][0];
228                     } else temp=spt;
229                 }
230                 flag[temp]^=1;
231             }
232         }
233         done=false;
234         outp(spt);
235         printf("\n");
236         scanf("%d%d",&n,&m);
237     }
238 
239     return 0;
240 }
View Code

 

 

 

转载于:https://www.cnblogs.com/jcf94/p/4374315.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/291586.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

WIN32程序结构

windows程序基于消息驱动系统&#xff0c;用户的所有行为和事件都被windows转成消息。windows内部对消息的处理:消息生命周期:1.消息产生:windows监控所有具体输入事件硬件设备。当系统收到设备输入事件时。windows将对应事件转成消息。2.消息投递:每个消息都有一个目标窗体接收…

linux之vim/vi快速复制多行内容的快捷键

1、复制一行 之前我只知道复制哪一行就把光标放在哪一行然后用命令y或者yy明亮,就复制了&#xff0c;然后我再用p命令就可以把这行复制到光标下面 2、复制多行 我们可以使用命令v然后加上 “上下键”&#xff0c;在vim可以看到部分文本变颜色&#xff0c;就像在windows系统下的…

zsh

2019独角兽企业重金招聘Python工程师标准>>> 1. MAC安装zsh后,部分bash 指令失效conda, list, pip, list失效&#xff0c;怎么解决&#xff1f; step1&#xff1a;vim ~/.bash_profile 记录Anaconda的路径地址: export PATH"/Users/XXX/anaconda/bin:$PAT…

导出jar插件_Fluttify输出的Flutter插件工程详解

系列文章&#xff1a;yohom&#xff1a;Fluttify输出的Flutter插件工程详解​zhuanlan.zhihu.comyohom&#xff1a;开发Flutter插件必备原生SDK->Dart接口生成引擎Fluttify介绍​zhuanlan.zhihu.comyohom&#xff1a;如何使用Fluttify开发一个新的Flutter插件​zhuanlan.zhi…

[免费下载应用]iNeuKernel.Ocr 图像数据识别与采集原理和产品化应用

目 录1..... 应用概述... 22..... 免费下载试用... 23..... 视频介绍... 24..... iNeuLink.Ocr图像数据采集应用... 25..... 数据上传到iNeuOS工业互联网操作系统... 46..... Ocr基本概念... 71. 应用概述在工业、军工或航天等领域&#xff0c;有些设备及软件系统比较陈…

hdu 1848(Fibonacci again and again)(SG博弈)

Fibonacci again and again Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 8380 Accepted Submission(s): 3462 Problem Description任何一个大学生对菲波那契数列(Fibonacci numbers)应该都不会陌生&#xff…

linux c之gcc编译出现error:lvalue required as unary ‘‘ operand解决办法

1、问题 今天搞epoll实现io复用的时候gcc编译出现这个错误lvalue required as unary & operand&#xff0c;如下图 2、解决办法 accept函数参数如下 int accept(int sockfd,struct sockaddr *addr,socklen_t *addrlen); 在第三个参数为了少些代码我是这样写成这样&size…

生成arff文件,csv转为arff

一、什么是arff格式文件 1、arff是Attribute-Relation File Format缩写&#xff0c;从英文字面也能大概看出什么意思。它是weka数据挖掘开源程序使用的一种文件模式。由于weka是个很出色的数据挖掘开源项目&#xff0c;所以使用的比较广&#xff0c;这也无形中推广了它的数据存…

数据库映射模式

数据库映射模式 关系数据库映射模式 四类架构模式&#xff1a; Row Data GatewayTable Data Gateway 此两种模式中不包含领域逻辑&#xff0c;包含所有数据访问逻辑&#xff0c;内存模型与关系表结构完全相同。Active Record 此模式将领域逻辑与数据访问扩及封装在一个对象中Da…

python字符串创建_在Python上创建完整的字符串

我需要在葡萄牙语字符串上执行词干.为此,我使用nltk.word_tokenize()函数对字符串进行标记,然后单独生成每个单词.之后,我重建了字符串.它工作正常,但表现不佳.我怎样才能让它更快&#xff1f;字符串长度约为200万字.tokenAux""tokens nltk.word_tokenize(portugues…

linux之Vim用快捷键快速移动光标至行首和行尾

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程 1、Vim用快捷键快速移动光标至行首 1&#xff09;按home键 2&#xff09;按住shift 6 键 3&#xff09;按住大写 I 键&#xff0c;按住了…

C#中的类

前言今天咱们简单复习下C#中类的相关知识。在刚开始学习编程的时候&#xff0c;都是从面向过程的C语言开始的&#xff0c;它有个特征就是有其执行顺序&#xff0c;先干这&#xff0c;再干那&#xff0c;很直接&#xff0c;也很好理解。但现在学习C#或者JAVA等面向对象的语言&am…

运维服务器信息收集

运维服务器信息收集 运维服务器信息收集; 作为一个运维&#xff0c;我们新服务器上架时有很多头疼的事。其中数据收集在我看来就是一个比较恶心的事。以下来讨论一下数据收集方面我的一此想法和做法&#xff0c;欢迎板砖^_^ 一&#xff0e;供货商的“特殊服务” 供 货商通常是选…

Stopwatch类学习

1、概述:给一条大MSDN的链接关于Stopwatch类最详细的教程 ,然后看着教程自己手动敲一边,加深映象,好记性不如烂键盘,哈哈,开个玩笑&#xff01; 2、类位置:这个类在哪里,这个是重点,虽然C#IDE很强大,但是我们还是得简单的了解下。通过一段代码来说明: using System; namespace …

linux之vim如何快速找到第二次打开文件的指定行

1、得到指定行的行号 vim 1.c 打开这个文件之后&#xff0c;比如有一行内容为 int main() 我们需要知道这是在哪一行&#xff0c;我们可以通过set nu命令来显示vim的行数,在vim里面用下面命令 :set nu 然后显示行数了&#xff0c;如果这个时候我们可以知道int main()在哪一行了…

epoch训练时间不同_tesnorflow实现N个epoch训练数据读取的办法

方式一&#xff1a;不显示设置读取N个epoch的数据&#xff0c;而是使用循环&#xff0c;每次从训练的文件中随机读取一个batch_size的数据&#xff0c;直至最后读取的数据量达到N个epoch。说明&#xff0c;这个方式来实现epoch的输入是不合理。不是说每个样本都会被读取到的。对…

看看这套WPF开源基础控件库:WPFDevelopers

此项目包含了 微信公众号 《 WPF开发者》 日常开发分享&#xff0c;欢迎Star。运行环境 Visual Studio 2019&#xff0c;dotNet Framework 4.0 SDK欢迎关注微信公众号支持贡献者DrawPrize&#xff08;WPF 实现大转盘抽奖&#xff09;GIF帧数太多&#xff0c;无法上传&#xff0…

如何将EDM营销与多渠道推广方式相结合

目前&#xff0c;消费者每天都会从各种渠道收到信息&#xff0c;如果仅用单一渠道的营销会影响整体营销。多渠道推广方式是所有渠道都要兼顾到从而接触用户&#xff0c;让他接收到他想接收的信息&#xff0c;多渠道的过程中邮件还是非常好的营销方式。你要想让你的EDM营销获得成…

Cannot resolve the collation conflict between SQL_Latin1_General_CP1_CI_AS and Latin1_General_100...

ErrorMessage Cannot resolve the collation conflict between "SQL_Latin1_General_CP1_CI_AS" and "Latin1_General_100_CI_AS" in the equal to operation. 查看SQL Server的Collation SELECT SERVERPROPERTY (Collation) Solution 1. 在安装SQL Server…

linux网络编程之用epoll实现io复用(基于tcp)

1、epoll介绍 epoll是在2.6内核中提出的,是之前的select和poll的增强版本。相对于select和poll来说,epoll更加灵活,没有描述符限制。epoll使用一个文件描述符管理多个描述符,将用户关系的文件描述符的事件存放到内核的一个事件表中,这样在用户空间和内核空间的copy只需一次…