20605移动盒子
难度级别:B; 运行时间限制:1000ms; 运行空间限制:51200KB; 代码长度限制:2000000B
试题描述

你有一行盒子,从左到右依次编号为1,2,3,……,n。可以执行一下四种指令:
    1、1 X Y表示将盒子 X 移动到盒子 Y 的左边。(如果X已经在Y的左边则忽略此指令)
    2、2 X Y表示把盒子X移动到盒子Y的右边。(如果X已经在Y的右边则忽略此指令)
    3、3 X Y表示交换盒子X和Y的位置。
    4、4表示反转整条链。
输入指令保证合法,即X不等于Y。

输入
第一行包括两个正整数n和m,分别表示盒子个数和指令条数,接下来的m行,每行一条指令,如果是指令1、2或者3时,三部分间有一个空格分隔,如指令1 2 4表示将盒子2移动到盒子4的左边。
输出
一个正整数,表示所有奇数位置上盒子编号的数字之和。
输入示例
6 4
1 1 4
2 3 5
3 1 6
4
输出示例
12
其他说明
样例说明:当n=6时,在初始状态下执行1 1 4后,盒子序列为2 3 1 4 5 6,接下来执行2 3 5后,盒子序列变成2 1 4 5 3 6,再执行3 1 6,得到2 6 4 5 3 1,最终执行4,得到1 3 5 4 6 2。
0 < n, m < 100001

题解:赤裸裸的链表,可惜我没有写。我写的是splay tree你们怕不怕!!!

写完真的是太爽了。。。

 #include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<queue>
#include<cstring>
#define PAU putchar(' ')
#define ENT putchar('\n')
#define CH for(int d=0;d<=1;d++) if(ch[d])
using namespace std;
const int maxn=+;
struct node{
node*fa,*ch[];
int c;bool rev;int siz;
node(){c=-;rev=false;siz=;}
void revt(){swap(ch[],ch[]);rev^=;return;}
void update(){siz=;CH{siz+=ch[d]->siz;}return;}
void down(){if(rev){CH{ch[d]->revt();}rev=false;}return;}
}Splay[maxn],*root;int cnt=;
int parent(node*x,node*&y){return (y=x->fa)?y->ch[]==x?:y->ch[]==x?:-:-;}
void rotate(node*x){
node*y,*z;int d1=parent(x,y),d2=parent(y,z);
if(y->ch[d1]=x->ch[d1^]) y->ch[d1]->fa=y;
y->fa=x;x->fa=z;x->ch[d1^]=y;
if(d2!=-) z->ch[d2]=x;
y->update();return;
}
void pushdown(node*x){
static node*s[maxn];int top=;
for(node*y;;x=y){
s[top++]=x;y=x->fa;
if(!y||(y->ch[]!=x&&y->ch[]!=x)) break;
} while(top--) s[top]->down();return;
}
node*splay(node*x){
pushdown(x);node*y,*z;int d1,d2;
while(true){
if((d1=parent(x,y))<) break;
if((d2=parent(y,z))<){rotate(x);break;}
if(d1==d2) rotate(y),rotate(x);
else rotate(x),rotate(x);
} x->update();return x;
}
node*find(node*x,int rank){
x->down();int kth=;if(x->ch[]) kth=x->ch[]->siz+;
if(rank==kth) return x;
if(rank<kth) return find(x->ch[],rank);
else return find(x->ch[],rank-kth);
}
void split(node*&x,node*&y,int a){
if(!a){y=x;x=NULL;return;}
x=splay(find(x,a));y=x->ch[];
x->ch[]=NULL;if(y)y->fa=NULL;x->update();return;
}
void split(node*&x,node*&y,node*&z,int a,int b){
split(x,z,b);split(x,y,a-);return;
}
void join(node*&x,node*y){
if(!x){x=y;return;}if(!y)return;
x=splay(find(x,x->siz));x->ch[]=y;
if(y)y->fa=x;x->update();return;
}
void join(node*&x,node*y,node*z){
join(y,z);join(x,y);return;
}
int A[maxn],n,Q;
void build(node*&x,int L,int R){
if(L>R)return;int M=L+R>>;
x=&Splay[cnt++];x->c=A[M];
build(x->ch[],L,M-);
build(x->ch[],M+,R);
if(x->ch[]) x->ch[]->fa=x;
if(x->ch[]) x->ch[]->fa=x;
x->update();return;
}
void reverse(int L,int R){
node*x,*y;split(root,x,y,L,R);x->revt();join(root,x,y);return;
}
node*findll(node*x,int a){
if(!x) return NULL;x->down();
if(x->c==a) return x;
node*t;
if((t=findll(x->ch[],a))||(t=findll(x->ch[],a))) return t;
return NULL;
}
void printer(node*x){
if(!x){printf("NULL ");return;}
x->down();
if(x->ch[])printer(x->ch[]);
printf("%d ",x->c);
if(x->ch[])printer(x->ch[]);
return;
}
int cz=;long long sum=;
void counter(node*x){
if(!x){return;}
x->down();
if(x->ch[])counter(x->ch[]);
if((cz++)&) sum+=x->c;
if(x->ch[])counter(x->ch[]);
return;
}
node*findfa(node*x){
while(x->fa) x=x->fa;return x;
}
int findpos(int a){
for(int i=;i<=n;i++) if(A[i]==a) return i;
return -;
}
void split(node*&t1,node*&x,node*&t2,node*&y,node*&t3,int a,int b){
splay(t1);
x=findll(t1,a),y=findll(t1,b);
splay(x);int kth1=;if(x->ch[]) kth1=x->ch[]->siz+;
splay(y);int kth2=;if(y->ch[]) kth2=y->ch[]->siz+;
if(kth1>kth2) swap(kth1,kth2);
splay(t1);split(t1,x,t2,kth1,kth1);
kth2-=kth1;split(t2,y,t3,kth2,kth2);return;
}
void join(node*&t1,node*x,node*t2,node*y,node*t3){
join(t2,y,t3);join(t1,x,t2);return;
}
void swapnode(int a,int b){
node*t1,*t2,*x,*y;
split(root,x,t1,y,t2,a,b);
join(root,y,t1,x,t2);return;
}
void shift(int a,int b,int tp){//1 right 0 left
node*t1,*t2,*x,*y;
split(root,x,t1,y,t2,a,b);
y->ch[tp]=x;x->fa=y;y->update();
join(root,NULL,t1,y,t2);return;
}
inline int read(){
int x=,sig=;char ch=getchar();
while(!isdigit(ch)){if(ch=='-')sig=-;ch=getchar();}
while(isdigit(ch))x=*x+ch-'',ch=getchar();
return x*=sig;
}
inline void write(int x){
if(x==){putchar('');return;}if(x<)putchar('-'),x=-x;
int len=,buf[];while(x)buf[len++]=x%,x/=;
for(int i=len-;i>=;i--)putchar(buf[i]+'');return;
}
inline void write(long long x){
if(x==){putchar('');return;}if(x<)putchar('-'),x=-x;
int len=;long long buf[];while(x)buf[len++]=x%,x/=;
for(int i=len-;i>=;i--)putchar(buf[i]+'');return;
}
void init(){
n=read();Q=read();
for(int i=;i<=n;i++) A[i]=i;
build(root,,n);int tp,a,b;
while(Q--){
tp=read();
if(tp==) root->revt();
else{
a=read();b=read();
if(tp==) swapnode(a,b);
else shift(a,b,tp-);
}
}
counter(root);
write(sum);
return;
}
void work(){
return;
}
void print(){
return;
}
int main(){init();work();print();return ;}

COJ 0018 移动盒子的更多相关文章

  1. 谈谈一些有趣的CSS题目(二)-- 从条纹边框的实现谈盒子模型

    开本系列,讨论一些有趣的 CSS 题目,抛开实用性而言,一些题目为了拓宽一下解决问题的思路,此外,涉及一些容易忽视的 CSS 细节. 解题不考虑兼容性,题目天马行空,想到什么说什么,如果解题中有你感觉 ...

  2. 认识W3C标准盒子模型,理解外边距叠加

    概述: 注:加粗斜体字是非常重要的概念,决定着你是不是能看懂那句话,所以不懂的请一定要搜索一下. 页面上的每个元素,都在一个矩形框里.   每个矩形框都是一个盒模型.   每个盒模型都由内容区域(co ...

  3. 《Web开发中让盒子居中的几种方法》

    一.记录下几种盒子居中的方法: 1.0.margin固定宽高居中: 2.0.负margin居中: 3.0.绝对定位居中: 4.0.table-cell居中: 5.0.flex居中: 6.0.trans ...

  4. CSS3之盒子模型

    display:box 使子元素成行排列如果父级宽度小于子级盒子 不会把超出部分挤出下面 而是直接超出 -box-orient:vertical 使盒子垂直显示  默认水平显示 -box-direct ...

  5. 让div盒子相对父盒子垂直居中的几种方法

    div相对于父盒子垂直居中的几种方法,之前在网上看到很多种方法,确实说的很对,也很具体,但是我感觉对于初学者来说,一目了然是最重要的,所以,我把很高深的技巧,和很复杂的css样式都剔除掉,旨在让更多人 ...

  6. 盒子 offsetLeft、offsetTop、offsetWidth、getBoundingClientRect等属性解释

    offsetLeft 获取的是忽略 margin 当前元素距离上一级父节点(有没有设置position,有的话依据父节点,没有的话依据页面最左端这时候不管滚动条移到哪) 当前元素向左的位置 记住它会将 ...

  7. JS学习:第二周——NO.3盒子模型

    1.CSS盒子模型包括四个部分组成:设定的宽高+padding+border+margin: 2.JS盒子模型:通过系统提供的属性和方法,来获取当前元素的样式值   JS提供的属性和方法: clien ...

  8. 学习微信小程序之css12设置盒子内容的宽高

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  9. html学习第三天—— 第11章 盒子模型 div

    盒模型--边框(一) 盒子模型的边框就是围绕着内容及补白的线,这条线你可以设置它的粗细.样式和颜色(边框三个属性). 如下面代码为div来设置边框粗细为2px.样式为实心的.颜色为红色的边框: div ...

随机推荐

  1. DFU工作过程中USB机制

    在一级bootloader执行进入USB启动方式之后,设备进行枚举.枚举过程中会通过PC端发送命令对连接的USB设备进行枚举.当枚举成功之后,在PC端可以看到设备的盘符. 当设备能够被PC正确识别之后 ...

  2. Android URI简单介绍

    就Android平台而言,URI主要分三个部分:scheme, authority and path.当中authority又分为host和port.格式例如以下: scheme://host:por ...

  3. [AWS] Install the AWS cli

    On Windows, just download the installer and install it. Configure: aws configure In your aws console ...

  4. 三星笔记本R428安装xp win7双系统,切换系统重启才能进入系统解决办法。

    三星笔记本 XP win7 双系统切换重启解决方法 三星笔记本有个奇怪的现象,就是装有XP和win7双系统    xp切换到win7.进系统是会重启一次,并且bios回复光驱为第一启动项,win7切换 ...

  5. 基于 Quartz 开发企业级任务调度应用--转

    Quartz 基本概念及原理 Quartz Scheduler 开源框架 Quartz 是 OpenSymphony 开源组织在任务调度领域的一个开源项目,完全基于 Java 实现.该项目于 2009 ...

  6. 第一篇:数据工程师眼中的智能电网(Smart Grid)

    前言 想必第一次接触到智能电网这个概念的人,尤其是互联网从业者,都会顾名思义的将之理解为"智能的电网". 然而智能电网中的"智能"是广义上的智能,它就是指更好的 ...

  7. Android ViewPager 打造炫酷欢迎页

    Android ViewPager 打造炫酷欢迎页 ViewPager是Android扩展v4包中的类,这个类可以让用户切换当前的View.对于这个类的应用场景,稍加修改就可以应用到多个环境下.比如: ...

  8. 模拟电路"虚短" & "虚断"

    <虚短 & 虚断> 运算放大器组成的电路五花八门,令人眼花瞭乱,是模拟电路中学习的重点.遍观所有模拟电子技朮的书籍和课程,在介绍运算放大器电路的时候,无非是先给电路来个定性,比如这 ...

  9. Android 连接 SQL Server (jtds方式)——下

    本文主要补充介绍jtds的查询方法,将以博主的一个实际开发程序进行说明 下图是项目的文件列表与界面效果:          运行效果: 1.三个EditText对应的是单个计划的序号.品种名.数量 2 ...

  10. Android深入浅出之 AudioTrack分析

    Android深入浅出之Audio 第一部分 AudioTrack分析 一 目的 本文的目的是通过从Audio系统来分析Android的代码,包括Android自定义的那套机制和一些常见类的使用,比如 ...