HDU3487 splay最核心的功能是将平衡树中的节点旋转到他的某个祖先的位置,并且维持平衡树的性质不变。

两个操作(数组实现)

cut l,r, c把[l,r]剪下来放到剩下序列中第c个后面的位置.

flip l r 把[l,r]翻转(lazy标记,每次交换左右节点)

cut思路:把l-1旋到根,r+1旋到根的右节点,取下这一段;在剩下的序列中找到c,c+1的位置,把c旋到根,c+1旋到右节点,插入。

由平衡树性质易证得是对的(中序遍历恒定)

flip思路:把l-1旋到根,r+1旋到右节点,打上lazy标记。

调数据结构的代码 是坠痛苦滴 不过一个人的命运当然要靠自我奋斗

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<vector>
#include<queue>
#include<algorithm>
using namespace std;
const int maxn=400000; int Root,n,m;
struct Node
{
int val,cnt,size;
bool rev;
int father;int lson;int rson;
Node(int v,int c,int fa,int l,int r)
{this->val=v;this->cnt=c;this->father=fa;this->lson=l;this->rson=r;rev=false;}
}tren[maxn]=Node(0,0,0,0,0); queue<int> memq; int newnode()
{
int loc=memq.front();memq.pop();
return loc;
} void dele(int loc)
{
memq.push(loc);
return ;
} void pushdown(int x)
{
if(x==0)return ;
if(tren[x].rev)
{
tren[x].rev=false;
swap(tren[x].lson,tren[x].rson);
if(tren[x].lson!=0)tren[tren[x].lson].rev=!tren[tren[x].lson].rev;
if(tren[x].rson!=0)tren[tren[x].rson].rev=!tren[tren[x].rson].rev;
}
} void update(int x)
{
tren[x].size=tren[x].cnt;
if(tren[x].lson!=0)tren[x].size+=tren[tren[x].lson].size;
if(tren[x].rson!=0)tren[x].size+=tren[tren[x].rson].size;
} void zig(int x)
{
int fa=tren[x].father;
pushdown(fa);pushdown(x);
if(tren[tren[fa].father].lson==fa){tren[tren[fa].father].lson=x;}
else {tren[tren[fa].father].rson=x;}
tren[x].father=tren[fa].father;
tren[fa].father=x;
tren[fa].lson=tren[x].rson;
tren[tren[x].rson].father=fa;
tren[x].rson=fa;
update(tren[x].rson);update(x);update(tren[x].father);
//swap(tren[fa],tren[x]);
} void zag(int x)
{
int fa=tren[x].father;
pushdown(fa);pushdown(x);
if(tren[tren[fa].father].lson==fa){tren[tren[fa].father].lson=x;}
else {tren[tren[fa].father].rson=x;}
tren[x].father=tren[fa].father;
tren[fa].father=x;
tren[fa].rson=tren[x].lson;
tren[tren[x].lson].father=fa;
tren[x].lson=fa;
update(tren[x].lson);update(x);update(tren[x].father);
//swap(tren[fa],tren[x]);
} void splay(int root,int now)//核心
{
if(root==0||now==0)return ;
int end=tren[root].father;
while(tren[now].father!=end)
{
if(tren[now].father==root)
{
if(tren[tren[now].father].lson==now)zig(now);
else zag(now);
return ;
}
int fa=tren[now].father;int grand=tren[fa].father;
if(tren[grand].lson==fa)
{
if(tren[fa].lson==now){zig(fa);zig(now);continue;}
else{zag(now);zig(now);continue;}
}
else{
if(tren[fa].rson==now){zag(fa);zag(now);continue;}
if(tren[fa].lson==now){zig(now);zag(now);continue;}
}
}
return ;
} int insert(int fa,int root,int value)
{
int ans;
pushdown(root);
if(root==0)
{
root=newnode();
tren[root]=Node(value,1,fa,0,0);
update(root);
ans= root;
//splay(1,root);
}
if(tren[root].val==value)
{tren[root].cnt++;update(root);ans=0;}
if(tren[root].val>value)
{
if(tren[root].lson==0)
{
tren[root].lson=newnode();
tren[tren[root].lson]=Node(value,1,root,0,0);
update(tren[root].lson);
// splay(1,tren[root].lson);
ans= tren[root].lson;
}
else ans= insert(root,tren[root].lson,value);
}
else
{
if(tren[root].rson==0)
{
tren[root].rson=newnode();
tren[tren[root].rson]=Node(value,1,root,0,0);
update(tren[root].rson);
//splay(1,tren[root].rson);
ans= tren[root].rson;
}
else ans= insert(root,tren[root].rson,value);
}
update(root);
return ans;
} int access(int root,int key)
{
pushdown(root);
if(tren[root].val==key)return root;
if(tren[root].val<key)return access(tren[root].rson,key);
else return access(tren[root].lson,key);
} int Max(int root)
{
pushdown(root);
if(root==0||tren[root].rson==0)return root;
else return Max(tren[root].rson);
} int join(int l,int r)
{
if(l==0)return r;
if(r==0)return l;
int max=Max(l);
splay(l,max);
tren[max].rson=r;
return max;
} void erase(int root,int key)
{
int now=access(root,key);
int fa=tren[now].father;
if(tren[now].cnt>1){tren[now].cnt--;return ;}
else
{
if(tren[fa].lson==now){tren[fa].lson=join(tren[now].lson,tren[now].rson);}
else{tren[fa].rson=join(tren[now].lson,tren[now].rson);}
}
return ;
} int getKth(int root,int k)
{
while(root!=0&&k<=tren[root].size)
{
pushdown(root);
int ls=tren[root].lson,rs=tren[root].rson;
if(ls!=0&&k<=tren[ls].size){root=ls;continue;}
k-=tren[root].cnt;
if(ls!=0)k-=tren[ls].size;
if(k<=0){return root;}
root=rs;
}
} void maintain(int now,int val)
{
while(now!=0)
{
tren[now].size+=val;
now=tren[now].father;
}
}
vector<int>ans;
void print( int root)
{
if(root==0)return ;
pushdown(root);
print(tren[root].lson);
if(tren[root].val<=n&&tren[root].val>=1)ans.push_back(tren[root].val);
print(tren[root].rson);
} int main()
{freopen("t.txt","r",stdin);
freopen("1.txt","w",stdout); while(scanf("%d%d",&n,&m))
{
while(!memq.empty())memq.pop();
for(int i=2;i<min(n*2,400000);i++)
memq.push(i);
if(n<=0||m<=0)return 0;
tren[1]=Node(0,1,0,0,0);
update(1);
Root=1;
for(int i=1;i<=n+1;i++)
{
int newl=insert(0,Root,i);
splay(Root, newl);
Root=newl;
}
for(int i=1;i<=m;i++)
{
char ss[10];
scanf("%s",ss);
if(ss[0]=='C')
{
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
int klo=getKth(Root,a);
splay(Root,klo);
Root=klo;
klo=getKth(Root,b+2);
splay(tren[Root].rson,klo);
int tre=tren[klo].lson;
maintain(tren[tre].father,tren[tre].size*(-1));
tren[klo].lson=0;
klo=getKth(Root,c+1);
splay(Root,klo);
Root=klo;
klo=getKth(Root,c+2);
splay(tren[Root].rson,klo);
tren[klo].lson=tre;
tren[tre].father=klo;
maintain(tren[tre].father,tren[tre].size);
}
if(ss[0]=='F')
{
int a,b;
scanf("%d%d",&a,&b);
int klo=getKth(Root,a);
splay(Root,klo);
Root=klo;
klo=getKth(Root,b+2);
splay(tren[Root].rson,klo);
tren[ tren[tren[Root].rson].lson].rev=!tren[ tren[tren[Root].rson].lson].rev;
}
}
ans.clear();
print (Root);
for(int i=0;i<ans.size()-1;i++)
printf("%d ",ans[i]);
printf("%d\n",ans[ans.size()-1]);
}
return 0;
}

  

HDU3487 Play with Chain splay 区间反转的更多相关文章

  1. 算法模板——splay区间反转 2

    实现功能:同splay区间反转 1(基于BZOJ3223 文艺平衡树) 这次改用了一个全新的模板(HansBug:琢磨了我大半天啊有木有),大大简化了程序,同时对于splay的功能也有所完善 这里面没 ...

  2. HDU3487 Play With Chain [Splay]

    题目传送门 题目描述 Problem Description YaoYao is fond of playing his chains. He has a chain containing n dia ...

  3. 算法模板——splay区间反转 1

    实现的功能:将序列区间反转,并维护 详见BZOJ3223 var i,j,k,l,m,n,head,a1,a2:longint; s1:ansistring; a,b,c,d,fat,lef,rig: ...

  4. Splay 区间反转

    同样的,我们以一道题来引入. 传送门 这次的任务比较少,只要求进行区间反转.区间反转? 这个好像用啥都是O(n)的吧……(这次vector,set也救不了你了) 我们来使用splay解决这个问题.我们 ...

  5. hdu 1890 Robotic Sort(splay 区间反转+删点)

    题目链接:hdu 1890 Robotic Sort 题意: 给你n个数,每次找到第i小的数的位置,然后输出这个位置,然后将这个位置前面的数翻转一下,然后删除这个数,这样执行n次. 题解: 典型的sp ...

  6. HDU-3487 Play with Chain Splay tee区间反转,移动

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3487 对于一个数列有两种操作:1.CUT a b c,先取出a-b区间的数,然后把它们放在取出后的第c ...

  7. HDU--3487 Play with Chain (Splay伸展树)

    Play with Chain Problem Description YaoYao is fond of playing his chains. He has a chain containing ...

  8. HDU 1890 - Robotic Sort - [splay][区间反转+删除根节点]

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1890 Time Limit: 6000/2000 MS (Java/Others) Memory Li ...

  9. [bzoj3223]文艺平衡树(splay区间反转模板)

    解题关键:splay模板题. #include<cstdio> #include<cstring> #include<algorithm> #include< ...

随机推荐

  1. BZOJ 2693: jzptab 莫比乌斯反演 + 积性函数 +筛法

    Code: #include<bits/stdc++.h> #define ll long long #define M 10001000 #define maxn 10200100 #d ...

  2. Linux常用命令——目录处理命令

    1.建立目录:mkdir mkdir -p [目录名] -p 递归创建 命令英文原意:make directories 实例: [root@localhost ~]# ls anaconda-ks.c ...

  3. Python 爬虫爬取今日头条街拍上的图片

    # 今日头条--街拍 import requests from urllib.parse import urlencode import os from hashlib import md5 from ...

  4. LeetCode141LinkedListCycle和142LinkedListCycleII

    141题:判断链表是不是存在环! // 不能使用额外的存储空间 public boolean hasCycle(ListNode head) { // 如果存在环的 两个指针用不一样的速度 会相遇 L ...

  5. 【解题报告】洛谷 P2571 [SCOI2010]传送带

    [解题报告]洛谷 P2571 [SCOI2010]传送带今天无聊,很久没有做过题目了,但是又不想做什么太难的题目,所以就用洛谷随机跳题,跳到了一道题目,感觉好像不是太难. [CSDN链接](https ...

  6. python3支持excel读写

    1.安装setuptools-17.0.tar.gz cmd 进入命令行 cd C:\Users\vivi\Desktop\pythonforexcel\setuptools-17.0\setupto ...

  7. Datatable 插入一行数据到第一行

    var t = $('#passwdHOST').DataTable({ 'searching': true, 'ordering': false, 'autoWidth': false, dom: ...

  8. 洛谷 4251 [SCOI2015]小凸玩矩阵

    [题解] 二分答案+二分图匹配. 先二分最小值Min,然后扫一遍这个矩阵,把满足a[i][j]<=Min的i,j连边,之后跑二分图匹配,如果最大匹配数大于等于n-k+1,当前的Min即是合法的. ...

  9. UVALive 6510 Stickers

    Stickers Time Limit: 3000ms Memory Limit: 131072KB This problem will be judged on UVALive. Original ...

  10. 清北学堂模拟赛d1t1 位运算1(bit)

    题目描述LYK拥有一个十进制的数N.它赋予了N一个新的意义:将N每一位都拆开来后再加起来就是N所拥有的价值.例如数字123拥有6的价值,数字999拥有27的价值.假设数字N的价值是K,LYK想找到一个 ...