FALLEN_GEMINI的平衡树
FallenGemini · · 个人记录
题面改编自《SuperMemo》
题目描述
FALLEN_GEMINI 是个非常可爱的女孩子,喜欢敲敲代码,看看电视……
有一天,她打开电视,开始观看电视节目《SuperMemo》,而她的好朋友 Jackson 正在参加这个节目,于是他花了三七二十八力帮助了她的好朋友 Jackson 。
但我们可爱的女孩子 FALLEN_GEMINI 认为这样的电视节目还不够有趣,于是她邀请了她的小伙伴 屋顶上的小丑 参加她举办的电视节目《FALLEN_GEMINI的平衡树》。
参与者被告知要播放一个记忆游戏。
首先,主持人告诉参与者一系列数字
为了使节目更有趣,参与者有机会转向其他人,这意味着 屋顶上的小丑 在回答查询时感到困难,他可能会打电话给你寻求帮助。
你的任务是观看电视节目并编写一个程序,给出每个查询的正确答案,以便在他打电话时协助 屋顶上的小丑 。
输入格式
第一行一个整数
第二行
第三行一个整数
以下
输出格式
对于每个 正确的答案。
样例输入
10
1 2 3 4 5 6 7 8 9 10
9
Add 1 10 1
Reverse 2 8
Find 1 10 1
Find 2 5 3
Revolve 4 3 7
Insert 5 3
Delete 6
Find 5 6 6
Find 1 10 7
样例输出
2
8
11
7
样例解释
初始数列:
操作1 将区间
操作2 将区间
操作3 查询区间
操作4 查询区间
操作5 将区间
操作6 在第
操作7 删除第
操作8 查询区间
操作9 查询区间
子任务
其他
- 数据保证在任意时刻
A_i\le 10^9 。 - 数据保证所有操作区间
[\text{pos},\text{pos}+\text{len}-1] 均为序列的子区间。 - 数据保证
\text{pos}\ge 1 - 旋转操作可理解为将该区间最后一个数字提前到该区间最前
压行才是美学这道题怎么这么水啊,怎么全是基础操作啊,连区间最大子段和都没有,出题人怎么这么蒻啊(>﹏<)
code
因为题目太水了直接上代码吧
#include<bits/stdc++.h>
#define lson ch[x][0]
#define rson ch[x][1]
using namespace std;
const int MAXN=2e5+10;
const int inf=1e9+7;
int f[MAXN],ch[MAXN][2],lazy[MAXN],flag[MAXN],Min[MAXN],val[MAXN],size[MAXN];
vector<int> a;
vector<int>::iterator it;
//lazy 自己已经修改,子节点还没有修改 swap自己还没有交换
int n,m,tot,root;
char c[10];
int read(){int sss=0,fff=1;char ccc;ccc=getchar();while(ccc<'0'||ccc>'9'){if(ccc=='-')fff=-1;ccc=getchar();}while(ccc>='0'&&ccc<='9')sss=(sss<<1)+(sss<<3)+(ccc^'0'),ccc=getchar();return sss*fff;}
inline void updata(int x)//维护结点x的数据
{
if(!x) return;
size[x]=size[lson]+size[rson]+1;
Min[x]=min(val[x],min(Min[lson],Min[rson])+lazy[x]);
}
inline void updata_add(int x,int op)//维护lazy等区间性数据
{
if(!x) return;
val[x]+=op;lazy[x]+=op;Min[x]+=op;
}
inline void pushdown_swap(int x)//维护下传过程
{
swap(lson,rson);
flag[lson]^=1;flag[rson]^=1;
flag[x]=0;
}
inline void pushdown(int x)//下传结点x的lazy和旋转数据
{
if(!x) return;
if(lazy[x]) updata_add(lson,lazy[x]),updata_add(rson,lazy[x]),lazy[x]=0;
if(flag[x]) pushdown_swap(x);
}//下传数据
inline int get(int x)//先更新是否交换,再返回x是父亲的左/右孩子
{
pushdown(f[x]);
return ch[f[x]][1]==x;
}
inline void rotate(int x)//旋转结点x
{
int old=f[x],oldf=f[old],which=get(x);
pushdown(x);
ch[old][which]=ch[x][which^1];f[ch[old][which]]=old;
ch[x][which^1]=old;f[old]=x;
f[x]=oldf;
if(oldf) ch[oldf][ch[oldf][1]==old]=x;
updata(old);updata(x);
}
inline void splay(int x,int op)//旋转x至成为op的孩子
{
for(register int fa;(fa=f[x])!=op;rotate(x))
if(f[fa]!=op)
get(fa)==get(x)?rotate(fa):rotate(x);
if(!op) root=x;
}
inline int findx(int op)//返回排名为op的点的编号
{
int x=root;
while(true)
{
pushdown(x);
if(op<=size[lson]) x=lson;//在左子树上
else
{
op-=size[lson]+1;
if(!op) return x;//就是这个点
x=rson;
}
}
}//自带下传数据 找到排名为op的点
inline void back(int x)//更新数据至根
{
while(x) updata(x),x=f[x];
}
void newnode(int &rt,int v,int fa)//新建一个结点,值为v,父亲为fa
{
rt=++tot;f[rt]=fa;val[rt]=Min[rt]=v;size[rt]=1;
}
inline void insert(int k,int op)//在第k个后面添加一个结点
{
int l=findx(k),r=findx(k+1);
splay(l,0);splay(r,l);
newnode(ch[r][0],op,r);
updata(r);updata(l);
}
inline void add(int x,int y,int op)//区间[x,y]增加op
{
int l=findx(x),r=findx(y+2);
splay(l,0);splay(r,l);
updata_add(ch[r][0],op);
updata(r);updata(l);
}
inline int MIN(int x,int y)//返回区间[x,y]的最小值
{
int l=findx(x),r=findx(y+2);
splay(l,0);splay(r,l);
return Min[ch[r][0]];
}
inline void reverse(int x,int y)//翻转[x,y]
{
int l=findx(x),r=findx(y+2);
splay(l,0);splay(r,l);
int k=ch[r][0];
flag[k]^=1;
}
inline void revolve(int x,int y,int T)//旋转[x,y]T次
{
int l=findx(x),r=findx(y+2),k=findx(y+1-T),st=findx(x+1);
splay(l,0);splay(r,l);splay(k,r);
ch[st][0]=ch[k][1];ch[k][1]=0;f[ch[st][0]]=st;
back(st);
}
inline void del(int op)//删除排名为op的点
{
int l=findx(op),r=findx(op+2);
splay(l,0);splay(r,l);
ch[r][0]=0;
updata(r);updata(l);
}
inline void init()//初始化
{
memset(Min,0x3f3f3f3f,sizeof(Min));
root=1;tot=2;val[0]=Min[0]=inf;
val[1]=inf;Min[1]=inf;ch[1][1]=2;size[1]=2;//左哨兵
val[2]=inf;Min[2]=inf;f[2]=1;size[2]=1;//右哨兵
}
inline void GET(int x)
{
if(!x) return;
pushdown(x);
a.push_back(val[x]);
GET(lson);GET(rson);
}
inline int Find(int x,int y,int k)
{
int l=findx(x),r=findx(y+2);
splay(l,0);splay(r,l);
a.clear();GET(ch[r][0]);//读入整个区间
it=a.begin()+k-1;
nth_element(a.begin(),it,a.end());
return *it;
}
int main()
{
// freopen("bt.in","r",stdin);
// freopen("bt.out","w",stdout);
init();n=read();
for(register int i=1;i<=n;++i) insert(i,read());
m=read();
for(int i=1;i<=m;i++)
{
int pos,len,x,op,T,k;
scanf("%s",c);
if(c[0]=='A') pos=read(),len=read(),op=read(),add(pos,pos+len-1,op);
else if(c[0]=='I') x=read(),pos=read(),insert(pos+1,x);
else if(c[0]=='F')
{
pos=read();len=read();k=read();
if(k==1) printf("%d\n",MIN(pos,pos+len-1));
else printf("%d\n",Find(pos,pos+len-1,k));
}
else if(c[0]=='D') pos=read(),del(pos);
else if(c[3]=='o') {pos=read(),len=read(),T=read(),T%=len;if(T) revolve(pos,pos+len-1,T);}
else if(c[3]=='e') pos=read(),len=read(),reverse(pos,pos+len-1);
}
return 0;
}