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】 反转卡片的更多相关文章

  1. [codevs1743]反转卡片

    [codevs1743]反转卡片 试题描述 [dzy493941464|yywyzdzr原创] 小A将N张卡片整齐地排成一排,其中每张卡片上写了1~N的一个整数,每张卡片上的数各不相同. 比如下图是N ...

  2. codevs 1743 反转卡片 rope or splay

    [codevs1743]反转卡片 题目描述 Description [dzy493941464|yywyzdzr原创] 小A将N张卡片整齐地排成一排,其中每张卡片上写了1~N的一个整数,每张卡片上的数 ...

  3. codevs 1743 反转卡片

    题目描述 Description [dzy493941464|yywyzdzr原创] 小A将N张卡片整齐地排成一排,其中每张卡片上写了1~N的一个整数,每张卡片上的数各不相同. 比如下图是N=5的一种 ...

  4. Codevs 1743 反转卡片(splay)

    1743 反转卡片 时间限制: 2 s 空间限制: 256000 KB 题目等级 : 大师 Master 题目描述 Description [dzy493941464|yywyzdzr原创] 小A将N ...

  5. 【集训第四天·继续刷题】之 lgh怒刚ypj

    继续水题,终于完全掌握了伸展树了,好心痛QAQ. 1.codevs1343 蚱蜢 区间最大值查询+单点移动 最大值查询维护一个mx数组就行,单点移动么,先删除在插入 CODE: /* PS: 比较ma ...

  6. ●Splay的一些题

    ●个人感觉: 代码长: 函数多: (很套路): (很强的Splay,无愧于“区间王”) ●NOI2005维修数列 一个可以当模板学习的题,包含了众多操作(函数): 区间插入,删除,更新,翻转,询问信息 ...

  7. IOIOI卡片占卜(Atcoder-IOIOI カード占い)(最短路)

    题目描述: K 理事長は占いが好きで,いつも様々な占いをしている.今日は,表の面に ‘I’ が,裏の面に ‘O’ が書か れたカードを使って今年の IOI での日本選手団の出来を占うことにした. 占い ...

  8. 简谈百度坐标反转至WGS84的三种思路

    文章版权由作者李晓晖和博客园共有,若转载请于明显处标明出处:http://www.cnblogs.com/naaoveGIS/ 1.背景 基于百度地图进行数据展示是目前项目中常见场景,但是因为百度地图 ...

  9. .Net Core MVC 网站开发(Ninesky) 2.3、项目架构调整-控制反转和依赖注入的使用

    再次调整项目架构是因为和群友dezhou的一次聊天,我原来的想法是项目尽量做简单点别搞太复杂了,仅使用了DbContext的注入,其他的也没有写接口耦合度很高.和dezhou聊过之后我仔细考虑了一下, ...

随机推荐

  1. C#中excel导入sql

    using Microsoft.Office.Interop.Excel; public int ledinExcel(string file, object sender, EventArgs e) ...

  2. DEDECMS之二 如何修改模板页

    使用织梦系统最经常是为了仿站,那么模板应该怎么改? 这里主要谈谈关于比较常用的几个模板页 网站主页.列表页.内容页.栏目的调用 1.主页模板 常用组合方法:index.htm + head.htm + ...

  3. UIScrollView增加刷新

    1. if (!self.scrollView) { CGRect frame = CGRectMake(0.0, 0.0, CGRectGetWidth(self.view.frame), CGRe ...

  4. CGI、FastCGI和PHP-FPM关系图解

    CGI.FastCGI和PHP-FPM关系图解   webapp即是php解析器等 当Web Server收到 index.php 这个请求后,会启动对应的 CGI 程序,这里就是PHP的解析器.接下 ...

  5. Linux 网络编程详解四(流协议与粘包)

    TCP/IP协议是一种流协议,流协议是字节流,只有开始和结束,包与包之间没有边界,所以容易产生粘包,但是不会丢包. UDP/IP协议是数据报,有边界,不存在粘包,但是可能丢包. 产生粘包问题的原因 . ...

  6. C#——Marshal.StructureToPtr方法简介

    目录 MarshalStructureToPtr方法简介 功能及位置 语法 参数说明 异常 备注 举例 本博客(http://blog.csdn.net/livelylittlefish)贴出作者(三 ...

  7. MPI+WIN10并行试运行

    系统:2015 win10专业版 x64 MPI安装包:mpich2-1.4.1p1-win-x86-64.man 将后缀改为.msi 以管理员身份安装 安装过程一路默认,注意<behappy为 ...

  8. Zepto的天坑汇总

    前言 最近在做移动端开发,用的是zepto,发现他跟jquery比起来称之为天坑不足为过,但是由于项目本身原因,以及移动端速度要求的情况下,也只能继续用下去. 所以在这里做一下汇总 对img标签空sr ...

  9. 用js转换joson返回数据库的时间格式为/Date(*************)/

    原理是取中间的毫秒数,再转换成js的Date类型 function ChangeDateFormat(val) { if (val != null) { var date = new Date(par ...

  10. List<T>与Dictionary<string,T>频繁检索的性能差距

    一直对LINQ简洁高效的语法青睐有加,对于经常和资料库,SQL语法打交道的C#开发者来说,LINQ无疑是一个非常不错的选择,当要在List<T>(T为一个普通对象)集合中查找满足某些条件的 ...