COJ 0018 移动盒子
20605移动盒子 |
难度级别:B; 运行时间限制:1000ms; 运行空间限制:51200KB; 代码长度限制:2000000B |
试题描述
|
你有一行盒子,从左到右依次编号为1,2,3,……,n。可以执行一下四种指令: |
输入
|
第一行包括两个正整数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 移动盒子的更多相关文章
- 谈谈一些有趣的CSS题目(二)-- 从条纹边框的实现谈盒子模型
开本系列,讨论一些有趣的 CSS 题目,抛开实用性而言,一些题目为了拓宽一下解决问题的思路,此外,涉及一些容易忽视的 CSS 细节. 解题不考虑兼容性,题目天马行空,想到什么说什么,如果解题中有你感觉 ...
- 认识W3C标准盒子模型,理解外边距叠加
概述: 注:加粗斜体字是非常重要的概念,决定着你是不是能看懂那句话,所以不懂的请一定要搜索一下. 页面上的每个元素,都在一个矩形框里. 每个矩形框都是一个盒模型. 每个盒模型都由内容区域(co ...
- 《Web开发中让盒子居中的几种方法》
一.记录下几种盒子居中的方法: 1.0.margin固定宽高居中: 2.0.负margin居中: 3.0.绝对定位居中: 4.0.table-cell居中: 5.0.flex居中: 6.0.trans ...
- CSS3之盒子模型
display:box 使子元素成行排列如果父级宽度小于子级盒子 不会把超出部分挤出下面 而是直接超出 -box-orient:vertical 使盒子垂直显示 默认水平显示 -box-direct ...
- 让div盒子相对父盒子垂直居中的几种方法
div相对于父盒子垂直居中的几种方法,之前在网上看到很多种方法,确实说的很对,也很具体,但是我感觉对于初学者来说,一目了然是最重要的,所以,我把很高深的技巧,和很复杂的css样式都剔除掉,旨在让更多人 ...
- 盒子 offsetLeft、offsetTop、offsetWidth、getBoundingClientRect等属性解释
offsetLeft 获取的是忽略 margin 当前元素距离上一级父节点(有没有设置position,有的话依据父节点,没有的话依据页面最左端这时候不管滚动条移到哪) 当前元素向左的位置 记住它会将 ...
- JS学习:第二周——NO.3盒子模型
1.CSS盒子模型包括四个部分组成:设定的宽高+padding+border+margin: 2.JS盒子模型:通过系统提供的属性和方法,来获取当前元素的样式值 JS提供的属性和方法: clien ...
- 学习微信小程序之css12设置盒子内容的宽高
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- html学习第三天—— 第11章 盒子模型 div
盒模型--边框(一) 盒子模型的边框就是围绕着内容及补白的线,这条线你可以设置它的粗细.样式和颜色(边框三个属性). 如下面代码为div来设置边框粗细为2px.样式为实心的.颜色为红色的边框: div ...
随机推荐
- CF 295E Yaroslav and Points(Splay)
题目大意: 两个操作 1 id op 把id的位置+op 2 id op 查询在[id.op]之间的全部的数的差 思路: 关键是pushup函数. 自己退一下会发现.跟区间的总和,区间的节点个数有 ...
- android string.xml里的空格字符
在string.xml定义字符串的时候常常要用到空格, 直接用键盘敲的话不知道是几个空格,常常看错了,导致误删. 假设用 来替代空格的话,就好非常多. 另外使用%1$s,%1$d能够在一个字符串里定义 ...
- Android---用动画来处理布局的变化
本文译自:http://developer.android.com/training/animation/layout.html 布局动画一种系统预装的动画,每次布局配置发生变化时,系统会运行它.你所 ...
- diy 电脑 重装系统
1\组装好电脑 2\硬盘的红灯只亮一会,找不到 硬盘 .bios里 硬盘设置里 IDE修改为 ACHI即可. 3\老毛桃 \ 用桌面的那个分区软件 分区 100G,300G 4\找到U盘 的iso 文 ...
- 浅谈Android架构之MVP,MVVM
概述 MVP(Model-View-Presenter)是传统MVC(Model-View-Controller)在Android开发上的一种变种.进化模式.主要用来隔离UI.UI逻辑和业务逻辑.数据 ...
- Activity 【生命周期】
不同情况下的回调 我们打开应用时先后调用了onCreate()->onStart()->onResume 当我们按BACK键时,我们这个应用程序将结束,这时候我们将先后调用onPause( ...
- java中的数据库事务处理
/*java使用事务处理,首先要求数据库支持事务,如使用MYSQL的事务功能,就要求mysql的表类型为Innodb,*/ /*InnoDB,是MySQL的数据库引擎之一 与传统的ISAM与MyISA ...
- 我的github今天大手笔分享,welcome——fork
看项目名就知道是什么样子的demo,还包含了数据库文件,welcome fork!
- c#隐式转换之有符号位转换
有符号位类型的转换,额外的高位用源表达式的符号位填充.这样就维持了被转换的值的正确符号和大小. 特别注意的是负数的转换,额外的高位用1填充,因为负数的二进制表示是对应正数的二进制取反加1,所以高位用1 ...
- 装饰者模式(Decorator)
首先来看一个例子: 比如,饮料可以分为很多种类,而这里我取一个咖啡,那么这个咖啡呢,有多种形式的, 比如有加糖了的咖啡,有加奶的咖啡,也有加热了的咖啡,也有加了冰块的咖啡. 而各个顾客的选择却是不同的 ...