[2016北京集训测试赛5]小Q与内存-[线段树的神秘操作]

时间:2023-03-09 22:56:26
[2016北京集训测试赛5]小Q与内存-[线段树的神秘操作]

Description

[2016北京集训测试赛5]小Q与内存-[线段树的神秘操作]

Solution

哇真的异常服气。。线段树都可以搞合并和拆分的啊orzorz。神的世界我不懂

Code

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;
const int M=;
const int N=;
int sz[M],lc[M],rc[M],tag[M],rt[N],all_work,cnt;
int _new(int x=)
{
int o=++cnt;
tag[o]=x-;
sz[o]=<<tag[o];
lc[o]=rc[o]=;
return cnt;
}
void pushdown(int o)
{
if (!tag[o]) return;
lc[o]=_new(tag[o]);
rc[o]=_new(tag[o]);
tag[o]=;
}
int split(int o,int k)
{
int now=++cnt,re=now;
pushdown(o);
while (lc[o]||rc[o])
{
tag[now]=;sz[now]=k;sz[o]-=k;
if (k<=sz[lc[o]])
{
lc[now]=_new();rc[now]=;
now=lc[now];o=lc[o];
} else
{
rc[now]=_new();lc[now]=lc[o];
k-=sz[lc[o]];lc[o]=;
now=rc[now];o=rc[o];
}
pushdown(o);
}
tag[now]=tag[o]=;
sz[now]=k;sz[o]-=k;
return re;
}
int merge(int x,int y)
{
if (!x||!y) return x+y;
lc[x]=merge(lc[x],lc[y]);
rc[x]=merge(rc[x],rc[y]);
sz[x]+=sz[y];
return x;
}
int query(int x,int k)
{
int o=rt[x];
if (x>all_work||k>=sz[o]) return -;
int re=;
while (lc[o]||rc[o])
{
re<<=;
if (lc[o]&&k<sz[lc[o]]) o=lc[o];
else k-=sz[lc[o]],re|=,o=rc[o];
}
return re*(<<tag[o])+k;
}
int T,n,root;
int _type,_k,_i,_p;
void clear()
{
cnt=all_work=;
root=_new();
}
int main()
{
scanf("%d",&T);
while (T--)
{
clear();
scanf("%d",&n);
for (int i=;i<=n;i++)
{
scanf("%d",&_type);
if (_type==)
{
scanf("%d",&_k);
all_work++;
rt[all_work]=;
if (sz[root]<_k) {printf("failed\n");continue;}
rt[all_work]=split(root,_k);
printf("ok\n");
}
if (_type==)
{
scanf("%d",&_i);
if (_i>all_work||!rt[_i]) {printf("failed\n");continue;}
root=merge(root,rt[_i]);rt[_i]=;
printf("ok\n");
}
if (_type==)
{
scanf("%d%d",&_i,&_p);
int ans=query(_i,_p);
if (ans!=-) printf("%d\n",ans);
else printf("failed\n");
}
}
}
}