代码库.docx
《代码库.docx》由会员分享,可在线阅读,更多相关《代码库.docx(243页珍藏版)》请在冰豆网上搜索。
代码库
伸展树
Asimpleproblemwithintegers
//POJ-3468Asimpleproblemwithintegers
//YouhaveNintegers,A1,A2,...,AN.Youneedtodealwithtwokindsofoperations.Onetypeofoperationistoaddsomegivennumbertoeachnumberinagiveninterval.Theotheristoaskforthesumofnumbersinagiveninterval.
//"Cabc"meansaddingctoeachofAa,Aa+1,...,Ab.-10000≤c≤10000.
//"Qab"meansqueryingthesumofAa,Aa+1,...,Ab.
//Hint:
Thesumsmayexceedtherangeof32-bitintegers.
#defineSIZE100010//树的容量
typedefinttype;//V的类型
#definekey(CH[CH[r][1]][0])//关键树
//--------------------------下面开始节点域声明-----------------------------
////////////////////////////
intCH[SIZE][2],P[SIZE];//0左1右、父
typeV[SIZE];//值
intlen;//资源使用量
////////////////////////////
intCNT[SIZE];//本棵树的节点个数
////////////////////////////
intADD[SIZE];//标记-是否加上ADD
longlongSUM[SIZE];//本树中最小的值
////////////////////////////
////////////////////////////
//--------------------------下面开始操作节点-------------------------------
intnewNode(){//新建一个节点(先从回收站里找)
returnlen++;
}
voidinitNode(intx,typev,intch0,intch1,intp){//初始化每个节点
V[x]=v;
CH[x][0]=ch0;
CH[x][1]=ch1;
P[x]=p;
CNT[x]=1;
SUM[x]=V[x]=v;
ADD[x]=0;
}
//--------------------------下面开始操作伸展树----------------------------
voidinitTree(){//只需掉一次,清资源,设NULL节点
len=1;//从1开始,0代表NULL
initNode(0,0,0,0,0);
CNT[0]=0;
}
structSplayTree{
intr;//根
//--------------------------下面是基本函数---------------------------
SplayTree(typelv,typerv){//创建一个带哨兵的空SplayTree,lv/rv赋值成任何其实无所谓
inta=newNode();
intb=newNode();
initNode(a,lv,0,b,0);
initNode(b,rv,0,0,a);
push_up(b);push_up(a);
r=a;
}
voidrotate(intx,boolc){//将节点i,c=0左旋转zag,c=1右旋转zig
inty=P[x];
push_down(CH[x][0]);
push_down(CH[x][1]);
push_down(CH[y][c]);
CH[y][!
c]=CH[x][c];
if(CH[x][c])P[CH[x][c]]=y;
CH[x][c]=y;
P[x]=P[y];
P[y]=x;
if(P[x])CH[P[x]][CH[P[x]][1]==y]=x;
elser=x;
push_up(y);
}
voidsplay(intx,intf=0){//表示把结点x转到结点f的下面,默认为节点x成为根
inty;
boolb1,b2;
push_down(x);
while((y=P[x])!
=f){//用到了P[0]=0来处理x=0的情况
if(P[y]==f){
rotate(x,CH[y][0]==x);
}else{
b1=(y==CH[P[y]][0]);
b2=(x==CH[y][0]);
rotate((b1^b2)?
x:
y,b2);
rotate(x,b1);
}
}
push_up(x);
}
//选择第rank个节点,并且将这个节点splay到f下面,从0开始
voidselect(intrank,intf=0){
if(rank>=CNT[r]||rank<0)return;
inti=r;
while(true){
push_down(i);
if(CNT[CH[i][0]]==rank)break;
if(CNT[CH[i][0]]>rank){
i=CH[i][0];
}else{
rank-=CNT[CH[i][0]]+1;
i=CH[i][1];
}
}
splay(i,f);
}
voidinterval(intbegin,intend){//选中[begin,end)左闭右开的区间
select(begin-1);
select(end,r);
}
//--------------------下面开始insert和remove----------------------
voidinsert(type*arr,intn){//在root后面插入arr(似满二叉树),assumen>0!
intx=newNode();
initNode(x,arr[n-1],insertDfs(arr,n-1,x),CH[r][1],r);
if(CH[x][1])P[CH[x][1]]=x;
CH[r][1]=x;
splay(x);
}
intinsertDfs(type*arr,intn,intfather){
if(n<=0)return0;
intidx=n/2;
intx=newNode();
initNode(x,arr[idx],insertDfs(arr,idx,x),insertDfs(arr+idx+1,n-idx-1,x),father);
push_up(x);
returnx;
}
//--------------------下面开始push----------------------
voidpush_up(intidx){
if(!
idx)return;
//断言此处idx没有任何标记!
!
!
!
!
!
!
!
!
!
CNT[idx]=CNT[CH[idx][0]]+CNT[CH[idx][1]]+1;
SUM[idx]=SUM[CH[idx][0]]+SUM[CH[idx][1]]+V[idx];
}
voidpush_down(intidx){
if(!
idx)return;
if(ADD[idx]){
if(CH[idx][0])ADD[CH[idx][0]]+=ADD[idx];
if(CH[idx][1])ADD[CH[idx][1]]+=ADD[idx];
V[idx]+=ADD[idx];
SUM[idx]+=(longlong)ADD[idx]*CNT[idx];
ADD[idx]=0;
}
}
//------------------------一些其他函数-------------------
voidaddKeyTree(intv){//将关键树每个节点都加上v
if(!
key)return;
ADD[key]+=v;
splay(key);
}
//-----------------------打印函数--------------------
voidoutputKeySUM(){
printf("%lld\n",SUM[key]);
}
};
intarr[SIZE];
intmain(){
intn,q;
inta,b,d;
charc;
while(scanf("%d%d",&n,&q)!
=EOF){
for(inti=0;iinitTree();
SplayTreesp(0,0);
sp.insert(arr,n);
while(q--){
scanf("%c%d%d",&c,&a,&b);
if(c=='Q'){
sp.interval(a,b+1);
sp.outputKeySUM();
}else{
scanf("%d",&d);
sp.interval(a,b+1);
sp.addKeyTree(d);
}
}
}
return0;
}
GSS6
/**
SPOJ-4487CanyouanswerthesequeriesVI
Ixy:
insertelementyatpositionx(betweenx-1andx).
Dx:
deletetheelementatpositionx.
Rxy:
replaceelementatpositionxwithy.
Qxy:
printmax{Ai+Ai+1+..+Aj|x<=i<=j<=y}.
*/
#defineSIZE200010//树的容量
typedefinttype;//V的类型
constintinf=10010;//inf
#definekey(CH[CH[r][1]][0])//关键树
//--------------------------下面开始节点域声明-----------------------------
////////////////////////////
intCH[SIZE][2],P[SIZE];//0左1右、父
typeV[SIZE];//值
intlen;//资源使用量
////////////////////////////
intCNT[SIZE];//本棵树的节点个数
////////////////////////////
intSUM[SIZE];//本树V的和
intLL[SIZE],RR[SIZE],MM[SIZE];//从左面连续的值的和,右面连续的值的和,连续的最大值的和
//--------------------------下面开始操作节点-------------------------------
intnewNode(){//新建一个节点(先从回收站里找)
returnlen++;
}
voidinitNode(intx,typev,intch0,intch1,intp){//初始化每个节点
V[x]=v;
CH[x][0]=ch0;
CH[x][1]=ch1;
P[x]=p;
CNT[x]=1;
SUM[x]=V[x];
MM[x]=LL[x]=RR[x]=V[x];
}
//--------------------------下面开始操作伸展树----------------------------
voidinitTree(){//只需掉一次,清资源,设NULL节点
len=1;//从1开始,0代表NULL
initNode(0,-inf,0,0,0);
CNT[0]=SUM[0]=0;
}
structSplayTree{
intr;//根
//--------------------------下面是基本函数---------------------------
SplayTree(typelv,typerv){//创建一个带哨兵的空SplayTree,lv/rv赋值成任何其实无所谓
inta=newNode();
intb=newNode();
initNode(a,lv,0,b,0);
initNode(b,rv,0,0,a);
push_up(b);push_up(a);
r=a;
}
voidrotate(intx,boolc){//将节点i,c=0左旋转zag,c=1右旋转zig
inty=P[x];
CH[y][!
c]=CH[x][c];
if(CH[x][c])P[CH[x][c]]=y;
CH[x][c]=y;
P[x]=P[y];
P[y]=x;
if(P[x])CH[P[x]][CH[P[x]][1]==y]=x;
elser=x;
push_up(y);
}
voidsplay(intx,intf=0){//表示把结点x转到结点f的下面,默认为节点x成为根
inty;
boolb1,b2;
while((y=P[x])!
=f){//用到了P[0]=0来处理x=0的情况
if(P[y]==f){
rotate(x,CH[y][0]==x);
}else{
b1=(y==CH[P[y]][0]);
b2=(x==CH[y][0]);
rotate((b1^b2)?
x:
y,b2);
rotate(x,b1);
}
}
push_up(x);
}
//选择第rank个节点,并且将这个节点splay到f下面,从0开始
voidselect(intrank,intf=0){
if(rank>=CNT[r]||rank<0)return;
inti=r;
while(true){
if(CNT[CH[i][0]]==rank)break;
if(CNT[CH[i][0]]>rank){
i=CH[i][0];
}else{
rank-=CNT[CH[i][0]]+1;
i=CH[i][1];
}
}
splay(i,f);
}
voidinterval(intbegin,intend){//选中[begin,end)左闭右开的区间
select(begin-1);
select(end,r);
}
//--------------------下面开始insert和remove----------------------
voidinsert(type*arr,intn){//在root后面插入arr(似满二叉树),assumen>0!
intx=newNode();
initNode(x,arr[n-1],insertDfs(arr,n-1,x),CH[r][1],r);
if(CH[x][1])P[CH[x][1]]=x;
CH[r][1]=x;
splay(x);
}
intinsertDfs(type*arr,intn,intfather){
if(n<=0)return0;
intidx=n/2;
intx=newNode();
initNode(x,arr[idx],insertDfs(arr,idx,x),insertDfs(arr+idx+1,n-idx-1,x),father);
push_up(x);
returnx;
}
intcutKeyTree(){//切断keyTree和父亲的联系而已,不将节点清除回收,并返回keyTree
if(!
key)return0;
intres=key;
key=P[res]=0;//清除
splay(CH[r][1]);
returnres;
}
//--------------------下面开始push----------------------
voidpush_up(intidx){
if(!
idx)return;
//断言此处idx没有任何标记!
!
!
!
!
!
!
!
!
!
CNT[idx]=CNT[CH[idx][0]]+CNT[CH[idx][1]]+1;
SUM[idx]=SUM[CH[idx][0]]+SUM[CH[idx][1]]+V[idx];//[]
LL[idx]=max(LL[CH[idx][0]],SUM[CH[idx][0]]+V[idx]+max(LL[CH[idx][1]],0));
RR[idx]=max(RR[CH[idx][1]],SUM[CH[idx][1]]+V[idx]+max(RR[CH[idx][0]],0));
MM[idx]=max(MM[CH[idx][0]],MM[CH[idx][1]]);
MM[idx]=max(MM[idx],V[idx]+max(0,RR[CH[idx][0]])+max(0,LL[CH[idx][1]]));
}
//------------------------一些其他函数-------------------
voidreplaceKeyTree(intv){
//assumeCNT[key]=1
V[key]=v;
splay(key);
}
//------------------以下是打印代码------------------------
voidoutputKeyMM(){
printf("%d\n",MM[key]);
}
};
intarr[SIZE];
intms(){
charc;
boolfu=false;
while(c=getchar(),c>'9'||c<'0')if(c=='-')fu=true;
intres;
for(res=c-'0';c=getchar(),c>='0'&&c<='9';res=res*10+c-'0');
if(fu)res=-res;
returnres;
}
intmain(){
intn,q,a,b;
charc;
n=ms();
initTree();
SplayTreesp(0,0);
for(inti=0;isp.insert(arr,n);
q=ms();
while(q--){
while(c=getchar(),c>'Z'||c<'A');
if(c=='I'){
a=ms();b=ms();
sp.select(a-1);
sp.insert(&b,1);
}elseif(c=='D'){
a=ms();
sp.interval(a,a+1);
sp.cutKeyTree();
}elseif(c=='R'){
a=ms();b=ms();
sp.interval(a,a+1);
sp.replaceKeyTree(b);
}elseif(c=='Q'){
a=ms();b=ms();
sp.interval(a,b+1);
sp.outputKeyMM();
}elsewhile
(1);
}
return0;
}
GSS6_WHU
constintmaxq=100000+2000;
constintmaxn=100000+maxq;
structnode{
intval,size;
intsum,ml,mr,mc;
node*ch[2],*pre;
}*null,*root,*S[maxn],data[maxn];
inttot,top,tmp[maxq];
inlinenode*New_Node(intx){
node*p;
if(top)