#include <cstdio>
#include <cstdlib>
#ifndef LIST_H
#define LIST_H
struct Node;
struct List;
typedef Node* position;
typedef bool (*_cmpFunctor)(position _x,position _y);
typedef bool (*_predFunctor)(position _x);
struct Node {
int val;
position prev,succ;
Node() {}
Node(int _val,position _prev=NULL,position _succ=NULL) {
val=_val;
prev=_prev;
succ=_succ;
}
};
bool _greater(position _x,position _y) {
return _x->val<_y->val;
}
bool _less(position _x,position _y) {
return _x->val>_y->val;
}
bool _isdigit(position _x) {
return '0'<=_x->val&&_x->val<='9';
}
bool _isalpha(position _x) {
return 'a'<=_x->val&&_x->val<='z'||'A'<=_x->val&&_x->val<='Z';
}
_cmpFunctor greater=&_greater,less=&_less;
_predFunctor isalpha=&_isalpha,isdigit=&_isdigit;
struct List {
position _head,_tail;
List() {
_head=(position)malloc(sizeof(Node));
_tail=(position)malloc(sizeof(Node));
_head->succ=_tail;
_tail->prev=_head;
_head->prev=_tail->succ=NULL;
_head->val=_tail->val=0;
};
List(int *_arr,int _len) {
_head=(position)malloc(sizeof(Node));
_tail=(position)malloc(sizeof(Node));
_head->succ=_tail;
_tail->prev=_head;
_head->prev=_tail->succ=NULL;
_head->val=_tail->val=0;
while(--_len!=-1)insert(0,_arr[_len]);
}
List(long long *_arr,int _len) {
_head=(position)malloc(sizeof(Node));
_tail=(position)malloc(sizeof(Node));
_head->succ=_tail;
_tail->prev=_head;
_head->prev=_tail->succ=NULL;
_head->val=_tail->val=0;
while(--_len!=-1)insert(0,_arr[_len]);
}
List(char *_str) {
_head=(position)malloc(sizeof(Node));
_tail=(position)malloc(sizeof(Node));
_head->succ=_tail;
_tail->prev=_head;
_head->prev=_tail->succ=NULL;
_head->val=_tail->val=0;
while(*_str)insert(_tail,*_str++);
}
inline position begin() {
return _head->succ;
}
inline position end() {
return _tail;
}
inline int size() {
return _head->val;
}
inline int length() {
return _head->val;
}
void push_back(Node _x) {
insert(_tail,_x.val);
}
void push_back(position _x) {
insert(_tail,_x->val);
}
void push_front(Node _x) {
insert(begin(),_x.val);
}
void push_front(position _x) {
insert(begin(),_x->val);
}
position find(int _val,position _L=NULL,position _R=NULL) {
if(_L==NULL)_L=begin();
if(_R==NULL)_R=_tail;
position _toFind=_L;
while(_toFind!=_R) {
if(_toFind->val==_val)return _toFind;
_toFind=_toFind->succ;
}
return _toFind;
}
position lower_bound(int _val,position _L=NULL,position _R=NULL) {
if(_L==NULL)_L=begin();
if(_R==NULL)_R=_tail;
position _toFind=_L;
while(_toFind!=_R) {
if(_toFind->val>_val)return _toFind->prev;
_toFind=_toFind->succ;
}
return _toFind;
}
position upper_bound(int _val,position _L=NULL,position _R=NULL) {
if(_L==NULL)_L=begin();
if(_R==NULL)_R=_tail;
position _toFind=_L;
while(_toFind!=_R) {
if(_toFind->val>_val)return _toFind;
_toFind=_toFind->succ;
}
return _toFind;
}
position search_kth(int _k,position _L=NULL,position _R=NULL) {
if(_L==NULL)_L=_head,_k++;
if(_R==NULL)_R=_tail;
position _toFind=_L;
while(_toFind!=_R&&_k--) {
_toFind=_toFind->succ;
}
return _toFind;
}
void insert(position _pos,int _val) {
position _prevPos=_pos->prev,_newPos=(position)malloc(sizeof(Node));
_newPos->val=_val;
_newPos->succ=_prevPos->succ;
_prevPos->succ=_newPos;
_pos->prev=_newPos;
_newPos->prev=_prevPos;
_head->val++;
}
void insert(int k,int _val) {
insert(search_kth(k),_val);
}
void erase(position _pos) {
position _prevPos=_pos->prev;
_prevPos->succ=_pos->succ;
_prevPos->succ->prev=_prevPos;
free(_pos);
_head->val--;
}
void erase(int k) {
erase(search_kth(k));
}
void clear() {
while(begin()!=end())erase(begin());
}
void crash() {
while(begin()!=end())erase(begin());
free(_head);
free(_tail);
}
void merge(List _Llist,List _Rlist,_cmpFunctor _cmp = greater) {
position _L=_Llist.begin(),_R=_Rlist.begin();
while(_L!=_Llist.end()&&_R!=_Rlist.end()) {
if(_cmp(_L,_R)) {
push_back(_L);
_L=_L->succ;
} else {
push_back(_R);
_R=_R->succ;
}
}
while(_L!=_Llist.end()) {
push_back(_L);
_L=_L->succ;
}
while(_R!=_Rlist.end()) {
push_back(_R);
_R=_R->succ;
}
}
void split(List &_Llist,List &_Rlist,_predFunctor _pred) {
position _itr=begin();
while(_itr!=end()) {
if(_pred(_itr))_Llist.push_back(_itr);
else _Rlist.push_back(_itr);
_itr=_itr->succ;
}
}
void uni(List _A,List _B) {
List tem;
tem.merge(_A,_B);
position _itr=tem.begin()->succ,_temPos;
while(_itr!=tem.end()) {
_temPos=_itr;
_itr=_itr->succ;
if(_temPos->val==_temPos->prev->val)tem.erase(_temPos);
}
_head=tem._head;
_tail=tem._tail;
}
void dif(List _A,List _B) {
List tem;
tem.uni(_A,_B);
position _itr=tem.begin(),_Bitr=_B.begin(),_temPos;
while(_Bitr!=_B.end()&&_itr!=tem.end()) {
if(_Bitr->val==_Bitr->succ->val) {
_Bitr=_Bitr->succ;
continue;
}
if(_itr->val==_Bitr->val) {
_temPos=_itr;
_itr=_itr->succ;
tem.erase(_temPos);
_Bitr=_Bitr->succ;
} else _itr=_itr->succ;
}
_head=tem._head;
_tail=tem._tail;
}
void intersect(List _A,List _B) {
dif(_A,_B);
dif(_A,*this);
}
position _partion(position _L,position _R,_cmpFunctor _cmp = greater) {
int _temVal;
Node _LNode=*_L;
position _pivot=_L,_ptr=_L->succ;
while(_ptr!=_R) {
if(_cmp(_ptr,&_LNode)) {
_pivot=_pivot->succ;
_temVal=_pivot->val;
_pivot->val=_ptr->val;
_ptr->val=_temVal;
}
_ptr=_ptr->succ;
}
_temVal=_pivot->val;
_pivot->val=_L->val;
_L->val=_temVal;
return _pivot;
}
void sort(position _L=NULL,position _R=NULL,_cmpFunctor _cmp = greater) {
if(_L==NULL)_L=begin();
if(_R==NULL)_R=end();
if(_L!=_R) {
position _pivot = _partion(_L,_R,_cmp);
sort(_L,_pivot,_cmp);
sort(_pivot->succ,_R,_cmp);
}
}
void prt_Str() {
position itr=begin();
while(itr!=end()) {
printf("%c ",itr->val);
itr=itr->succ;
}
puts("");
}
void prt_Arr() {
position itr=begin();
while(itr!=end()) {
printf("%d ",itr->val);
itr=itr->succ;
}
puts("");
}
};
#endif