HDU 4286 Data Handler[スタック、両端キュー]
6501 ワード
分析転入:http://www.haogongju.net/art/1647260
この問題で考えやすいやり方はsplayですが、splayは書くのが面倒で、操作のたびにLogNの複雑さがあり、双方向チェーンテーブルも実現できますが、実践するのは面倒です.特に反転操作です.
毎回LまたはRが1ビット移動していることがわかり、反転操作に関連するため、2つのスタックでLの左側とRの右側のデータをそれぞれ格納し、LとRの中間のデータは1つの両端キューを使用して保存することができます.現在の両端キューのどちらが先頭で、どちらが末尾であるかを1つのdirで表すためです.
タイトルで与えられた7つの操作は,いずれもO(1)の複雑さで実現できるが,説明の便宜上,左スタックはLの左の数のスタックを表し,右スタックはRの右の数のスタックを表す.
1,MoveLeft L/R左シフト左ポインタは,左スタックのスタックトップの数を両端キューヘッダに弾き,左シフト右ポインタはキュー末尾の要素を右スタックに置く.
2,MoveRight L/R右シフト左ポインタはキューヘッダ要素を左スタックに配置し,右シフト右ポインタは右スタックトップ要素を両端キューの末尾に弾く.
3,Insert L Xがキューヘッダに挿入されます.
4,Insert R Xがキューの最後に挿入されます.
5,Delete Lキューヘッダ要素を削除します.
6,Delete Rキューの末尾要素を削除します.
7,Reverse dir^=1.
Code 1(両端キュー、スタックを配列でシミュレート):
Code 2(C++STL dequeで実現):
この問題で考えやすいやり方はsplayですが、splayは書くのが面倒で、操作のたびにLogNの複雑さがあり、双方向チェーンテーブルも実現できますが、実践するのは面倒です.特に反転操作です.
毎回LまたはRが1ビット移動していることがわかり、反転操作に関連するため、2つのスタックでLの左側とRの右側のデータをそれぞれ格納し、LとRの中間のデータは1つの両端キューを使用して保存することができます.現在の両端キューのどちらが先頭で、どちらが末尾であるかを1つのdirで表すためです.
タイトルで与えられた7つの操作は,いずれもO(1)の複雑さで実現できるが,説明の便宜上,左スタックはLの左の数のスタックを表し,右スタックはRの右の数のスタックを表す.
1,MoveLeft L/R左シフト左ポインタは,左スタックのスタックトップの数を両端キューヘッダに弾き,左シフト右ポインタはキュー末尾の要素を右スタックに置く.
2,MoveRight L/R右シフト左ポインタはキューヘッダ要素を左スタックに配置し,右シフト右ポインタは右スタックトップ要素を両端キューの末尾に弾く.
3,Insert L Xがキューヘッダに挿入されます.
4,Insert R Xがキューの最後に挿入されます.
5,Delete Lキューヘッダ要素を削除します.
6,Delete Rキューの末尾要素を削除します.
7,Reverse dir^=1.
Code 1(両端キュー、スタックを配列でシミュレート):
#include <algorithm>
#include <iostream>
#include <cstring>
#include <string>
#include <cstdio>
#include <vector>
#include <queue>
#include <cmath>
#include <map>
#include <set>
#define LL long long
#define pb push_back
#define Max(a,b) ((a)>(b)?(a):(b))
#define Min(a,b) ((a)<(b)?(a):(b))
using namespace std;
const int inf=0x3f3f3f3f;
const int maxn=1000005;
int cas,n,m,x[maxn],l,r;
int dq[maxn*2],head,tail;
int stkl[maxn],stkr[maxn];
char s1[20],s2[20];
int dir,topl,topr;
void init(){
topl=topr=dir=0;
head=maxn; tail=maxn-1;
for(int i=1;i<l;i++) stkl[++topl]=x[i];
for(int i=l;i<=r;i++) dq[++tail]=x[i];
for(int i=n;i>r;i--) stkr[++topr]=x[i];
}
void MoveLR(char op,char c){
if(op=='L'&&c=='L'){
if(!dir) dq[--head]=stkl[topl--];
else dq[++tail]=stkl[topl--];
}
else if(op=='R'&&c=='L'){
if(!dir) stkl[++topl]=dq[head++];
else stkl[++topl]=dq[tail--];
}
else if(op=='L'&&c=='R'){
if(!dir) stkr[++topr]=dq[tail--];
else stkr[++topr]=dq[head++];
}
else {
if(!dir) dq[++tail]=stkr[topr--];
else dq[--head]=stkr[topr--];
}
}
void Insert(char c){
int num;
scanf("%d",&num);
if(c=='L') {
if(!dir) dq[--head]=num;
else dq[++tail]=num;
}
else {
if(!dir) dq[++tail]=num;
else dq[--head]=num;
}
}
void Delete(char c){
if(c=='L'){
if(!dir) head++;
else tail--;
}
else {
if(!dir) tail--;
else head++;
}
}
void Reverse(){
dir^=1;
}
void print(){
int cnt=0;
for(int i=1;i<=topl;i++) x[++cnt]=stkl[i];
if(!dir) for(int i=head;i<=tail;i++) x[++cnt]=dq[i];
else for(int i=tail;i>=head;i--) x[++cnt]=dq[i];
for(int i=topr;i>0;i--) x[++cnt]=stkr[i];
for(int i=1;i<cnt;i++) printf("%d ",x[i]); printf("%d
",x[cnt]);
}
int main()
{
scanf("%d",&cas);
while(cas--){
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%d",&x[i]);
scanf("%d %d %d",&l,&r,&m);
init();
while(m--){
scanf("%s",s1);
if(s1[0]!='R') scanf("%s",s2);
switch(s1[0]){
case 'M':MoveLR(s1[4],s2[0]);break;
case 'I':Insert(s2[0]);break;
case 'D':Delete(s2[0]);break;
case 'R':Reverse();break;
}
}
print();
}
return 0;
}
Code 2(C++STL dequeで実現):
#include <algorithm>
#include <iostream>
#include <cstring>
#include <string>
#include <cstdio>
#include <vector>
#include <queue>
#include <cmath>
#include <map>
#include <set>
#define LL long long
#define pb push_back
#define pf push_front
#define Max(a,b) ((a)>(b)?(a):(b))
#define Min(a,b) ((a)<(b)?(a):(b))
using namespace std;
const int inf=0x3f3f3f3f;
const int maxn=1000005;
deque<int>a,b,c;
char s1[20],s2[20];
int num[maxn],n,m,dir,cas,l,r;
void init(){
dir=0;
a.clear(); b.clear(); c.clear();
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%d",&num[i]);
scanf("%d %d %d",&l,&r,&m);
for(int i=1;i<l;i++) a.pb(num[i]);
for(int i=l;i<=r;i++) b.pb(num[i]);
for(int i=r+1;i<=n;i++) c.pb(num[i]);
}
void MoveLR(char op,char ch){
if(op=='L'&&ch=='L'){
if(!dir) b.pf(*a.rbegin());
else b.pb(*a.rbegin());
a.pop_back();
}
else if(op=='R'&&ch=='L'){
if(!dir) a.pb(*b.begin()),b.pop_front();
else a.pb(*b.rbegin()),b.pop_back();
}
else if(op=='L'&&ch=='R'){
if(!dir) c.pf(*b.rbegin()),b.pop_back();
else c.pf(*b.begin()),b.pop_front();
}
else {
if(!dir) b.pb(*c.begin());
else b.pf(*c.begin());
c.pop_front();
}
}
void Insert(char ch){
int v;
scanf("%d",&v);
if(ch=='L') {
if(!dir) b.pf(v);
else b.pb(v);
}
else if(ch=='R'){
if(!dir) b.pb(v);
else b.pf(v);
}
}
void Delete(char ch){
if(ch=='L'){
if(!dir) b.pop_front();
else b.pop_back();
}
else {
if(!dir) b.pop_back();
else b.pop_front();
}
}
void Reverse(){
dir^=1;
}
void print(){
int cnt=0;
deque<int>::iterator it;
deque<int>::reverse_iterator rit;
for(it=a.begin();it!=a.end();it++) num[++cnt]=*it;
if(!dir) for(it=b.begin();it!=b.end();it++) num[++cnt]=*it;
else for(rit=b.rbegin();rit!=b.rend();rit++) num[++cnt]=*rit;
for(it=c.begin();it!=c.end();it++) num[++cnt]=*it;
for(int i=1;i<cnt;i++) printf("%d ",num[i]); printf("%d
",num[cnt]);
}
int main()
{
scanf("%d",&cas);
while(cas--){
init();
while(m--){
scanf("%s",s1);
if(s1[0]!='R') scanf("%s",s2);
switch(s1[0]){
case 'M':MoveLR(s1[4],s2[0]);break;
case 'I':Insert(s2[0]);break;
case 'D':Delete(s2[0]);break;
case 'R':Reverse();break;
}
}
print();
}
return 0;
}