【codevs1743】 反转卡片
http://codevs.cn/problem/1743/ (题目链接)
题意
给出一个序列{a1,a2,a3···},要求维护这样一种操作:将前a1个数反转,若第a1等于1,则停止操作。
Solution
像这种带有反转区间的操作,大概就是splay了。码了一个晚上。。。
splay一般就是处理区间反转,区间插入,区间删除这三种线段树等数据结构无法处理的操作,splay难写又难调,经常犯一些鬼畜错误,能不写就尽量不写的好。。splay不是二叉搜索树,但它有一个很优秀的性质:树的中序遍历出来的序列就是原始序列。这样我们方便的就可以处理区间上的问题,比如说对于区间[l,r],我们将l-1splay到树根,将r+1splay到树根的右儿子,那么我们要修改的区间就是树根的右儿子的左儿子子树。
所以对于这道题,我们每次反转时,先将splay两遍,然后再给节点[l,r]打上标记即可。代码模着hzwer写的,感觉很优秀。
代码
- // codevs1743
- #include<algorithm>
- #include<iostream>
- #include<cstdlib>
- #include<cstring>
- #include<cstdio>
- #include<cmath>
- #define LL long long
- #define inf 2147483640
- #define Pi acos(-1.0)
- #define free(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout);
- using namespace std;
- const int maxn=300010;
- int a[maxn],tr[maxn][2],fa[maxn],size[maxn],val[maxn],rev[maxn];
- int n,ans,rt;
- void rotate(int x,int &k) {
- int y=fa[x],z=fa[y],l,r;
- if (x==tr[y][0]) l=0;else l=1;
- r=l^1;
- if (y==k) k=x;
- else tr[z][tr[z][1]==y]=x;
- fa[y]=x;fa[x]=z;fa[tr[x][r]]=y;
- tr[y][l]=tr[x][r];tr[x][r]=y;
- //注意这里一定先更新y的size,再更新x的size.
- size[y]=size[tr[y][0]]+size[tr[y][1]]+1;
- size[x]=size[tr[x][0]]+size[tr[x][1]]+1;
- }
- void splay(int x,int &k) {
- while (x!=k) {
- int y=fa[x],z=fa[y];
- if (y!=k) { //如果x,y,z在一条链(形象)上,那么先旋y,再旋x.听说可以使平衡树更加平衡
- if (tr[z][0]==y ^ tr[y][0]==z) rotate(x,k); //不在一条链上
- else rotate(y,k); //在一条链上
- }
- rotate(x,k);
- }
- }
- void pushdown(int k) {
- int l=tr[k][0],r=tr[k][1];
- rev[k]^=1;rev[l]^=1;rev[r]^=1; //如果同一个区间被反转2次,那么就等价于不反转.
- swap(tr[k][0],tr[k][1]);
- }
- int find(int k,int x) { //在树中寻找序列中第rk个数
- if (rev[k]) pushdown(k);
- int l=tr[k][0],r=tr[k][1];
- if (size[l]+1==x) return k;
- else if (x<=size[l]) return find(l,x);
- else return find(r,x-size[l]-1);
- }
- void build(int l,int r,int f) {
- if (l>r) return;
- int mid=(l+r)>>1;
- //tr[][]记录当前节点的左儿子与右儿子
- if (mid<f) tr[f][0]=mid;
- else tr[f][1]=mid;
- //size[]记录子树大小,val[]记录数值,fa[]记录父亲.
- rev[mid]=0;val[mid]=a[mid];size[mid]=1;fa[mid]=f;
- if (l==r) return;
- build(l,mid-1,mid);
- build(mid+1,r,mid);
- size[mid]=size[tr[mid][0]]+size[tr[mid][1]]+1;
- }
- void rever(int l,int r) {
- int x=find(rt,l),y=find(rt,r+2);
- splay(x,rt);splay(y,tr[rt][1]);
- rev[tr[y][0]]^=1;
- }
- int main() {
- scanf("%d",&n);
- for (int i=1;i<=n;i++) scanf("%d",&a[i+1]);
- build(1,n+2,0);rt=(3+n)>>1;
- int ans=0;
- while (val[find(rt,2)]!=1) {
- ans++;
- rever(1,val[find(rt,2)]);
- if (ans>100000) {printf("-1");return 0;}
- }
- printf("%d",ans);
- return 0;
- }
【codevs1743】 反转卡片的更多相关文章
- [codevs1743]反转卡片
[codevs1743]反转卡片 试题描述 [dzy493941464|yywyzdzr原创] 小A将N张卡片整齐地排成一排,其中每张卡片上写了1~N的一个整数,每张卡片上的数各不相同. 比如下图是N ...
- codevs 1743 反转卡片 rope or splay
[codevs1743]反转卡片 题目描述 Description [dzy493941464|yywyzdzr原创] 小A将N张卡片整齐地排成一排,其中每张卡片上写了1~N的一个整数,每张卡片上的数 ...
- codevs 1743 反转卡片
题目描述 Description [dzy493941464|yywyzdzr原创] 小A将N张卡片整齐地排成一排,其中每张卡片上写了1~N的一个整数,每张卡片上的数各不相同. 比如下图是N=5的一种 ...
- Codevs 1743 反转卡片(splay)
1743 反转卡片 时间限制: 2 s 空间限制: 256000 KB 题目等级 : 大师 Master 题目描述 Description [dzy493941464|yywyzdzr原创] 小A将N ...
- 【集训第四天·继续刷题】之 lgh怒刚ypj
继续水题,终于完全掌握了伸展树了,好心痛QAQ. 1.codevs1343 蚱蜢 区间最大值查询+单点移动 最大值查询维护一个mx数组就行,单点移动么,先删除在插入 CODE: /* PS: 比较ma ...
- ●Splay的一些题
●个人感觉: 代码长: 函数多: (很套路): (很强的Splay,无愧于“区间王”) ●NOI2005维修数列 一个可以当模板学习的题,包含了众多操作(函数): 区间插入,删除,更新,翻转,询问信息 ...
- IOIOI卡片占卜(Atcoder-IOIOI カード占い)(最短路)
题目描述: K 理事長は占いが好きで,いつも様々な占いをしている.今日は,表の面に ‘I’ が,裏の面に ‘O’ が書か れたカードを使って今年の IOI での日本選手団の出来を占うことにした. 占い ...
- 简谈百度坐标反转至WGS84的三种思路
文章版权由作者李晓晖和博客园共有,若转载请于明显处标明出处:http://www.cnblogs.com/naaoveGIS/ 1.背景 基于百度地图进行数据展示是目前项目中常见场景,但是因为百度地图 ...
- .Net Core MVC 网站开发(Ninesky) 2.3、项目架构调整-控制反转和依赖注入的使用
再次调整项目架构是因为和群友dezhou的一次聊天,我原来的想法是项目尽量做简单点别搞太复杂了,仅使用了DbContext的注入,其他的也没有写接口耦合度很高.和dezhou聊过之后我仔细考虑了一下, ...
随机推荐
- Java 集合系列03之 ArrayList详细介绍(源码解析)和使用示例
概要 上一章,我们学习了Collection的架构.这一章开始,我们对Collection的具体实现类进行讲解:首先,讲解List,而List中ArrayList又最为常用.因此,本章我们讲解Arra ...
- CefSharp的引用、配置、实例
CefSharp的引用.配置.实例与报错排除(源码) Winform下CefSharp的引用.配置.实例与报错排除 本文详细介绍了CefSharp在vs2013..net4.0环境下,创建Winfro ...
- Android开篇(转)
转自:http://gityuan.com/android/ 一.简述 Android系统非常庞大.错中复杂,其底层是采用Linux作为基底,上层采用包含虚拟机的Java层以及Native层,通过系统 ...
- Linux Linux程序练习十五(进程间的通信共享内存版)
/* * 题目: * 编写程序,要去实现如下功能: 父进程创建子进程1和子进程2.子进程1向子进程2发送可靠信号,并传送额外数据为子进程1的pid*2; 子进程2接受可靠信号的值,并发送给父进程,父进 ...
- shell 使用
echo -e "1\t2\t3" #-e echo -e "\e[1;31m This is red text \e[0m" #color echo -e & ...
- iframe在ios下无故扩大的问题探究
移动端页面内嵌了个 iframe,在 ios 下打开却发现页面怪异.比如 demo.代码如下: <!DOCTYPE html> <html lang="zh-CN" ...
- github开源:企业级应用快速开发框架CIIP WEB+WIN+移动端
简介 CIIP是基于XAF开发的开源信息系统框架.CIIP最常见的应用场景是基于数据库的企业级应用程序,例如供应链系统,ERP系统,MRP系统,CRM系统等. CIIP支持WEB版本.Windows桌 ...
- HTTP 状态代码表示什么意思?
HTTP 状态代码表示什么意思? 如果某项请求发送到您的服务器要求显示您网站上的某个网页,服务器将会返回 HTTP 状态码响应请求.此状态代码提供关于请求状态的信息,一些常见的状态代码为: 200 - ...
- 深入理解OOP(三):多态和继承(动态绑定和运行时多态)
在前面的文章中,我们介绍了编译期多态.params关键字.实例化.base关键字等.本节我们来关注另外一种多态:运行时多态, 运行时多态也叫迟绑定. 深入理解OOP(一):多态和继承(初期绑定和编译时 ...
- Linux进程间通信之信号量
春节过去了,真的过去一年了.在公司待了快一年了.2016希望自己变得越来越好. ps:上面那句话是年前写的,中间隔了那么久,自己也变懒了. 一.信号量 1,信号量本质是一个计数器,控制访问共享资源的最 ...