http://blog.csdn.net/bin314/article/details/7900427
对块状链表不熟悉的请移步
1.链表节点(block):
block加入模板
template<class ElemType>
构造函数
block<ElemType>(block<ElemType>* to,block<ElemType>* p):next(to),pre(p)
①:属性
ElemType data[MAXN];
int len ; /*本block有效数据的长度*/
bool rev ;
block<ElemType> *next , *pre ;
并添加基本操作:分割,合并,删除下一个块
②:分割
在本块的指定位置处分割
void split(int pos) /*分裂,在pos处,分裂成->[0,pos)->[pos,len)->*/
{
if( pos >= len || pos <= 0 ) return ; /*非法位置*/
if( this->rev )/*在某例中可能出现的反转情况*/
{
reverse(this->data,this->data+this->len);
this->rev = 0 ;
}
block<ElemType>* newblock = new block<ElemType>(this->next,this);
if( this->next != NULL ) this->next->pre = newblock ;
this->next = newblock ;
/*注意修改一些基本的field*/
newblock->len = len - pos ;
newblock->setData(data+pos,len-pos);<span style="white-space: pre;"> </span>/*赋值*/
this->len = pos ; /*完成[0,pos)的分裂*/
}
③:合并
本块合并掉下一块
bool Union() /*当下一块和本块数据之和 < maxn 的时候可以合并*/
{
block<ElemType>* nextBlock = this->next ;
if( nextBlock == NULL ) return false ;
if( nextBlock->len + this->len > maxn ) return false ;
/*合并*/
if( this->rev )
{
reverse(this->data,this->data+this->len);
this->rev = 0 ;
}
if( nextBlock->rev )
{
reverse(nextBlock->data,nextBlock->data+nextBlock->len);
nextBlock->rev = 0 ;
}
this->next = nextBlock->next ;
if( nextBlock->next != NULL ) nextBlock->next->pre = this ;
int i ;
for( i = 0 ; i < nextBlock->len ; i++) data[this->len++] = nextBlock->data[i] ;
delete nextBlock;
return true ;
}
bool Union() /*当下一块和本块数据之和 < maxn 的时候可以合并*/
{
block<ElemType>* nextBlock = this->next ;
if( nextBlock == NULL ) return false ;
if( nextBlock->len + this->len > maxn ) return false ;
/*合并*/
if( this->rev )
{
reverse(this->data,this->data+this->len);
this->rev = 0 ;
}
if( nextBlock->rev )
{
reverse(nextBlock->data,nextBlock->data+nextBlock->len);
nextBlock->rev = 0 ;
}
this->next = nextBlock->next ;
if( nextBlock->next != NULL ) nextBlock->next->pre = this ;
int i ;
for( i = 0 ; i < nextBlock->len ; i++) data[this->len++] = nextBlock->data[i] ;
delete nextBlock;
return true ;
}
④:删除
void del() /*delete the next block*/
{
block<ElemType> * nextBlock = this->next ;
if( nextBlock == NULL ) return ;
this->next = nextBlock->next ;
if( nextBlock->next != NULL ) nextBlock->next->pre = this ;
delete nextBlock ;
}
2.blocklist的编写
这里就是一个链表,节点为block,针对具体情况有不同的操作。
附个editor和反转列表完整代码(合并在一起了)
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <iostream>
#include <string>
#include <math.h>
#include <time.h>
#include <vector>
#include <queue>
#include <algorithm>
#define showArray(a,len) for( i = 0 ; i < len ; i++) printf("%d ",*(a+i)); puts("");
/************************************************************************/
/* 块状链表 */
/************************************************************************/
using namespace std;
/*
insert 3
1 2 3
insert 3
1 2 3
delete 3
show 9
*/
const int MAXN = 300 ;
template<class ElemType>
class block
{
public:
static int maxn ;
ElemType data[MAXN];
int len ; /*本block有效数据的长度*/
bool rev ;
block<ElemType> *next , *pre ;
block<ElemType>(block<ElemType>* to,block<ElemType>* p):next(to),pre(p)
{
len = 0 ;
rev = false ;
}
/*注意pos=0,len的情况
1 <= pos < len
*/
void split(int pos) /*分裂,在pos处,分裂成->[0,pos)->[pos,len)->*/
{
if( pos >= len || pos <= 0 ) return ; /*非法位置*/
if( this->rev )
{
reverse(this->data,this->data+this->len);
this->rev = 0 ;
}
block<ElemType>* newblock = new block<ElemType>(this->next,this);
if( this->next != NULL ) this->next->pre = newblock ;
this->next = newblock ;
/*注意修改一些基本的field*/
newblock->len = len - pos ;
//strcpy((char*)newblock->data,(char*)&data[pos]); /*完成[pos,len)的分裂*/
newblock->setData(data+pos,len-pos);
this->len = pos ; /*完成[0,pos)的分裂*/
}
bool Union() /*当下一块和本块数据之和 < maxn 的时候可以合并*/
{
block<ElemType>* nextBlock = this->next ;
if( nextBlock == NULL ) return false ;
if( nextBlock->len + this->len > maxn ) return false ;
/*合并*/
if( this->rev )
{
reverse(this->data,this->data+this->len);
this->rev = 0 ;
}
if( nextBlock->rev )
{
reverse(nextBlock->data,nextBlock->data+nextBlock->len);
nextBlock->rev = 0 ;
}
this->next = nextBlock->next ;
if( nextBlock->next != NULL ) nextBlock->next->pre = this ;
//strcpy((char*)&this->data[len],(char*)nextBlock->data);
int i ;
for( i = 0 ; i < nextBlock->len ; i++) data[this->len++] = nextBlock->data[i] ;
delete nextBlock;
return true ;
}
ElemType select(int k)
{
if( k < len && k >= 0 )
return data[k] ;
return 0 ;
}
void del() /*delete the next block*/
{
block<ElemType> * nextBlock = this->next ;
if( nextBlock == NULL ) return ;
this->next = nextBlock->next ;
if( nextBlock->next != NULL ) nextBlock->next->pre = this ;
delete nextBlock ;
}
void setData(ElemType array[],int len)
{
this->len = len ;
int i ;
for( i = 0 ; i < len ; i++) this->data[i] = array[i] ;
}
};
template<class ElemType>
int block<ElemType>::maxn = MAXN ;
template<class ElemType>
class CBlockList
{
public:
block<ElemType>* head ;
block<ElemType>* cur ; /*指向当前的block*/
int offset ; /*block内偏移*/
CBlockList<ElemType>()
{
head = new block<ElemType>(NULL,NULL);
cur = head ;
offset = -1 ;
}
/*一下是NOI2003 editor要求的操作*/
/*指针到第pos个位置去*/
void moveKth(int pos);
/*指针前移*/
void PREV();
/*指针前移*/
void NEXT();
/*输出指针后n个字符,指针位置不变*/
void get(int n);
/*删除指针后n个字符*/
void del(int n);
/*在指针后插入n个字符*/
void insert(ElemType array[],int n);
};
template<class ElemType>
void CBlockList<ElemType>::moveKth(int pos)
{
block<ElemType> *temp = head->next , *fa = head ;
int accumulation = 0 ;
while ( temp != NULL )
{
if( accumulation + temp->len >= pos ) break ;
fa = temp ; /*去掉fa faster*/
accumulation += temp->len ;
temp = temp->next ;
}
if( temp == NULL ) /*超出边界后,默认指向最后一个元素*/
{
cur = fa ;
this->offset = cur->len - 1 ; /*note:if there is no data in blocklist , offset = -1 */
}
else
{
cur = temp ;
this->offset = pos - accumulation - 1 ;
}
if( cur != NULL ) while(cur->Union());
}
template<class ElemType>
void CBlockList<ElemType>::PREV()
{
if( this->offset == -1 )
{
/*initial cur and offset */
if( head->next != NULL ) cur = head->next ;
}
else if( this->offset == 0 ) /*go to pre block's last data*/
{
if( cur != head->next ) /*if equals, there is no previous data*/
{
cur = cur->pre ;
this->offset = cur->len - 1 ;
}
else this->offset--;
}
else
{
this->offset--;
}
if( cur != NULL ) while(cur->Union());
}
template<class ElemType>
void CBlockList<ElemType>::NEXT()
{
if( this->offset == -1 )
{
/*initial cur and offset */
if( head->next != NULL ) cur = head->next , this->offset = 0 ;
}
else if( this->offset == cur->len - 1 ) /*go to pre block's last data*/
{
if( cur->next != NULL ) /*if not , there's no next data*/
{
cur = cur->next ;
this->offset = 0 ;
}
}
else
{
this->offset++;
}
if( cur != NULL ) while(cur->Union());
}
template<class ElemType>
void CBlockList<ElemType>::get(int n)
{
if( this->offset == -1 )
{
/*initial cur and this->offset */
if( head->next == NULL ) return ;
cur = head->next ;
}
block<ElemType> *temp ;
int i , pos ;
temp = cur ;
for ( i = 0 , pos = this->offset + 1 ; i < n ; i++,pos++)
{
if( pos == temp->len )
{
temp = temp->next ;
if( temp == NULL ) break;
pos = 0 ;
}
if( temp != NULL )
printf("%c",temp->select(pos));
}
puts("");
}
template<class ElemType>
void CBlockList<ElemType>::insert(ElemType array[],int n)
{
if( n <= 0 ) return ;
block<ElemType>* father , *next ;
if ( this->offset == -1 )
{
/*insert into the first block*/
next = head->next ; /*insert before head*/
father = head ;
}
else
{
/*split */
cur->split(this->offset+1);
next = cur->next ;
father = cur ;
}
int len , accumulation = 0 ;
do
{
block<ElemType>* newBlock = new block<ElemType>(NULL,father);
if( n > block<ElemType>::maxn ) len = block<ElemType>::maxn ;
else len = n ;
newBlock->setData(array+accumulation,len);
//newBlock->pre = father ;
/*father must not empty*/
father->next = newBlock ;
father = newBlock ;
n -= len ;
accumulation += block<ElemType>::maxn ;
}
while ( n > 0 ) ;
father->next = next ;
/*总是成对出现的,不要总忘了*/
if( next != NULL ) next->pre = father ;
/*note:revise cur*/
if( this->offset == -1 ) cur = head->next ;
if( cur != NULL ) while(cur->Union());
}
template<class ElemType>
void CBlockList<ElemType>::del(int n)
{
if( this->offset == -1 )
{
/*initial cur and offset */
if( head->next == NULL ) return ;
cur = head ;
}
else
{
/*先分割,分割时前pos个data在一起*/
cur->split(this->offset+1);
}
int accumulation = 0 ;
block<ElemType>* temp = cur->next ;
while ( temp != NULL )
{
if( temp->len + accumulation <= n )
{
/*delete the temp block*/
accumulation += temp->len ;
temp = temp->next ;
cur->del();
}
else
{
/*split temp block*/
if( n > accumulation )
{
temp->split(n-accumulation);
cur->del();
}
break ;
}
}
if( this->offset == -1 ) cur = head->next ;
/*合并*/
/*!!!找了半个多小时才找到的错误= =*/
if( cur != NULL ) while(cur->Union());
}
/************************************************************************/
/* editor指令操作: */
/* insert X */
/* delete X */
/* goto X */
/* pre */
/* next */
/* show X */
/************************************************************************/
class CEditor
{
public:
const int maxn ;
CEditor():maxn(1024*1024*2) { }
char array[1024*1024*2+10];
CBlockList<char> list ;
void handle()
{
char op[16] , ch ;
int i , x , pos , t;
scanf("%d",&t);
while(t--)
{
scanf("%s",op);
switch(tolower(op[0]))
{
case 'i':
scanf("%d",&x);
for( i = 0 ; i < x ; )
{
ch = getchar();
if( ch >= 32 && ch <= 126 ) array[i++] = ch ;
}
list.insert(array,x);
break;
case 'm':
scanf("%d",&pos);
list.moveKth(pos);
break;
case 'p':
list.PREV();
break;
case 'n':
list.NEXT();
break;
case 'g':
scanf("%d",&x);
list.get(x);
break;
case 'd':
scanf("%d",&x);
list.del(x);
break;
default:
;
}
}
}
};
template<class ElemType>
class CRevBlockList: public CBlockList<ElemType>
{
public:
void build(int n);
void rev(int l,int r);
void show();
};
template<class ElemType>
void CRevBlockList<ElemType>::rev(int l,int r)
{
this->moveKth(l-1);
block<ElemType> *temp = this->cur , *curNext , *tmp ;
this->cur->split(this->offset+1);
/*注意这种未分割的情况!!!*/
if( this->offset == -1 ) temp = this->cur->pre ;
this->moveKth(r);
this->cur->split(this->offset+1);
/*reverse (temp,cur] */
curNext = this->cur->next ;
temp->next = this->cur ;
tmp = temp ;
//if( this->cur == temp ) this->cur->rev ^= 1 ;
while ( this->cur != tmp )
{
this->cur->rev ^= 1 ;
temp->next = this->cur ;
this->cur->next = this->cur->pre ;
if( this->cur->pre != NULL ) this->cur->pre = temp ;
temp = this->cur ;
this->cur = this->cur->next ;
}
temp->next = curNext ;
if( curNext != NULL ) curNext->pre = temp ;
}
template<class ElemType>
void CRevBlockList<ElemType>::show()
{
int i ;
block<ElemType>* tmp = this->head->next ;
while ( tmp != NULL )
{
if( tmp->rev )
{
for( i = tmp->len - 1 ; i >= 0 ; i--) printf("%d ",tmp->data[i]);
}
else
{
for( i = 0 ; i < tmp->len ; i++) printf("%d ",tmp->data[i]);
}
tmp = tmp->next ;
}
puts("");
};
template<class ElemType>
void CRevBlockList<ElemType>::build(int n)
{
int i , j ;
block<ElemType>* tmp = new block<ElemType>(NULL,this->head) , *fa ;
fa = this->head ;
fa->next = tmp ;
for( i = 1 ; i <= n ; i++)
{
if( tmp->len == block<ElemType>::maxn )
{
fa = tmp ;
tmp = new block<ElemType>(NULL,fa) ;
fa->next = tmp ;
i--;
}
else
{
tmp->data[tmp->len++] = i ;
}
}
};
class CRevClient
{
public:
CRevBlockList<int> list ;
void handle()
{
int n , m , l , r ;
while (~scanf("%d%d",&n,&m))
{
list.build(n);
while (m--)
{
scanf("%d%d",&l,&r);
list.rev(l,r);
}
list.show();
}
}
};
int main()
{
CRevClient client ;
client.handle();
}