COJ 0018 移动盒子

 

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你们怕不怕!!!

写完真的是太爽了。。。

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cmath>
  4 #include<algorithm>
  5 #include<queue>
  6 #include<cstring>
  7 #define PAU putchar(' ')
  8 #define ENT putchar('\n')
  9 #define CH for(int d=0;d<=1;d++) if(ch[d])
 10 using namespace std;
 11 const int maxn=100000+10;
 12 struct node{
 13     node*fa,*ch[2];
 14     int c;bool rev;int siz;
 15     node(){c=-1;rev=false;siz=1;}
 16     void revt(){swap(ch[0],ch[1]);rev^=1;return;}
 17     void update(){siz=1;CH{siz+=ch[d]->siz;}return;}
 18     void down(){if(rev){CH{ch[d]->revt();}rev=false;}return;}
 19 }Splay[maxn],*root;int cnt=0;
 20 int parent(node*x,node*&y){return (y=x->fa)?y->ch[1]==x?1:y->ch[0]==x?0:-1:-1;}
 21 void rotate(node*x){
 22     node*y,*z;int d1=parent(x,y),d2=parent(y,z);
 23     if(y->ch[d1]=x->ch[d1^1]) y->ch[d1]->fa=y;
 24     y->fa=x;x->fa=z;x->ch[d1^1]=y;
 25     if(d2!=-1) z->ch[d2]=x;
 26     y->update();return;
 27 }
 28 void pushdown(node*x){
 29     static node*s[maxn];int top=0;
 30     for(node*y;;x=y){
 31         s[top++]=x;y=x->fa;
 32         if(!y||(y->ch[0]!=x&&y->ch[1]!=x)) break;
 33     } while(top--) s[top]->down();return;
 34 }
 35 node*splay(node*x){
 36     pushdown(x);node*y,*z;int d1,d2;
 37     while(true){
 38         if((d1=parent(x,y))<0) break;
 39         if((d2=parent(y,z))<0){rotate(x);break;}
 40         if(d1==d2) rotate(y),rotate(x);
 41         else rotate(x),rotate(x);
 42     } x->update();return x;
 43 }
 44 node*find(node*x,int rank){
 45     x->down();int kth=1;if(x->ch[0]) kth=x->ch[0]->siz+1;
 46     if(rank==kth) return x;
 47     if(rank<kth) return find(x->ch[0],rank);
 48     else return find(x->ch[1],rank-kth);
 49 }
 50 void split(node*&x,node*&y,int a){
 51     if(!a){y=x;x=NULL;return;}
 52     x=splay(find(x,a));y=x->ch[1];
 53     x->ch[1]=NULL;if(y)y->fa=NULL;x->update();return;
 54 }
 55 void split(node*&x,node*&y,node*&z,int a,int b){
 56     split(x,z,b);split(x,y,a-1);return;
 57 }
 58 void join(node*&x,node*y){
 59     if(!x){x=y;return;}if(!y)return;
 60     x=splay(find(x,x->siz));x->ch[1]=y;
 61     if(y)y->fa=x;x->update();return;
 62 }
 63 void join(node*&x,node*y,node*z){
 64     join(y,z);join(x,y);return;
 65 }
 66 int A[maxn],n,Q;
 67 void build(node*&x,int L,int R){
 68     if(L>R)return;int M=L+R>>1;
 69     x=&Splay[cnt++];x->c=A[M];
 70     build(x->ch[0],L,M-1);
 71     build(x->ch[1],M+1,R);
 72     if(x->ch[0]) x->ch[0]->fa=x;
 73     if(x->ch[1]) x->ch[1]->fa=x;
 74     x->update();return;
 75 }
 76 void reverse(int L,int R){
 77     node*x,*y;split(root,x,y,L,R);x->revt();join(root,x,y);return;
 78 }
 79 node*findll(node*x,int a){
 80     if(!x) return NULL;x->down();
 81     if(x->c==a) return x;
 82     node*t;
 83     if((t=findll(x->ch[0],a))||(t=findll(x->ch[1],a))) return t;
 84     return NULL;
 85 }
 86 void printer(node*x){
 87     if(!x){printf("NULL ");return;}
 88     x->down();
 89     if(x->ch[0])printer(x->ch[0]);
 90     printf("%d ",x->c);
 91     if(x->ch[1])printer(x->ch[1]);
 92     return;
 93 }
 94 int cz=1;long long sum=0;
 95 void counter(node*x){
 96     if(!x){return;}
 97     x->down();
 98     if(x->ch[0])counter(x->ch[0]);
 99     if((cz++)&1) sum+=x->c;
100     if(x->ch[1])counter(x->ch[1]);
101     return;
102 }
103 node*findfa(node*x){
104     while(x->fa) x=x->fa;return x;
105 }
106 int findpos(int a){
107     for(int i=1;i<=n;i++) if(A[i]==a) return i;
108     return -1;
109 }
110 void split(node*&t1,node*&x,node*&t2,node*&y,node*&t3,int a,int b){
111     splay(t1);
112     x=findll(t1,a),y=findll(t1,b);
113     splay(x);int kth1=1;if(x->ch[0]) kth1=x->ch[0]->siz+1;
114     splay(y);int kth2=1;if(y->ch[0]) kth2=y->ch[0]->siz+1;
115     if(kth1>kth2) swap(kth1,kth2);
116     splay(t1);split(t1,x,t2,kth1,kth1);
117     kth2-=kth1;split(t2,y,t3,kth2,kth2);return;
118 }
119 void join(node*&t1,node*x,node*t2,node*y,node*t3){
120     join(t2,y,t3);join(t1,x,t2);return;
121 }
122 void swapnode(int a,int b){
123     node*t1,*t2,*x,*y;
124     split(root,x,t1,y,t2,a,b);
125     join(root,y,t1,x,t2);return;
126 }
127 void shift(int a,int b,int tp){//1 right 0 left
128     node*t1,*t2,*x,*y;
129     split(root,x,t1,y,t2,a,b);
130     y->ch[tp]=x;x->fa=y;y->update();
131     join(root,NULL,t1,y,t2);return;
132 }
133 inline int read(){
134     int x=0,sig=1;char ch=getchar();
135     while(!isdigit(ch)){if(ch=='-')sig=-1;ch=getchar();}
136     while(isdigit(ch))x=10*x+ch-'0',ch=getchar();
137     return x*=sig;
138 }
139 inline void write(int x){
140     if(x==0){putchar('0');return;}if(x<0)putchar('-'),x=-x;
141     int len=0,buf[15];while(x)buf[len++]=x%10,x/=10;
142     for(int i=len-1;i>=0;i--)putchar(buf[i]+'0');return;
143 }
144 inline void write(long long x){
145     if(x==0){putchar('0');return;}if(x<0)putchar('-'),x=-x;
146     int len=0;long long buf[15];while(x)buf[len++]=x%10,x/=10;
147     for(int i=len-1;i>=0;i--)putchar(buf[i]+'0');return;
148 }
149 void init(){
150     n=read();Q=read();
151     for(int i=1;i<=n;i++) A[i]=i;
152     build(root,1,n);int tp,a,b;
153     while(Q--){
154         tp=read();
155         if(tp==4) root->revt();
156         else{
157             a=read();b=read();
158             if(tp==3) swapnode(a,b);
159             else shift(a,b,tp-1);
160         }
161     }
162     counter(root);
163     write(sum);
164     return;
165 }
166 void work(){
167     return;
168 }
169 void print(){
170     return;
171 }
172 int main(){init();work();print();return 0;}

 

转载于:https://www.cnblogs.com/chxer/p/4554991.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值