感觉又刚了一遍带插入区间k小值。。。
这题写个替罪羊练一下。其实应该可以用重量平衡的treap套trie。
带插入维护一段区间的trie和次小值。
区间次小值随便维护,区间trie呢?
我会做!替罪羊套trie!
不过写到一半你会发现这题还有删除。
treap删点直接旋到下面删。那替罪羊怎么删?
直接重构?每次删中间的点就挂了。
打标记? 似乎会有很多特判。
只要像线段树一样建就好了。把所有的表示元素的点都放在叶节点,其他点都是空点。只维护子树中所有叶节点形成的trie。
插入时新建两个点,删除时直接删除叶节点。
查询时像线段树一样找到log个区间,然后类似主席树地跑。
#include <bits/stdc++.h>
using namespace std;
#define A 20
#define alp 0.93
#define N 1100000
#define M 35000000
#define ls(x) ch[x][0]
#define rs(x) ch[x][1]
#define which(x) (ch[fa[x]][1]==x)
int a[N],n,m,n0,ans;
int st[210],top;
char s[11];
struct Trie
{
int ch[M][2],num[M],cnt;
queue<int>q;
int ap()
{
if(!q.empty())
{
int ret=q.front();q.pop();
ls(ret)=rs(ret)=0;num[ret]=0;
return ret;
}
return ++cnt;
}
void del(int x)
{
if(!x)return;
q.push(x);
del(ls(x));del(rs(x));
}
void insert(int &now,int v,int deep,int tp)
{
if(!now)now=ap();
num[now]+=tp;
if(deep==-1)return;
if(v>>deep&1)insert(rs(now),v,deep-1,tp);
else insert(ls(now),v,deep-1,tp);
}
int merge(int x,int y)
{
if(!x&&!y)return 0;
int ret=ap();
ls(ret)=merge(ls(x),ls(y));
rs(ret)=merge(rs(x),rs(y));
num[ret]=num[x]+num[y];
return ret;
}
int query(int x,int deep)
{
if(deep<0)return 0;
int t=x>>deep&1,sum=0;
for(int i=1;i<=top;i++)
sum+=num[ch[st[i]][t^1]];
for(int i=1;i<=top;i++)
st[i]=ch[st[i]][sum ? t^1:t];
return query(x,deep-1)+(sum ? 1<<deep:0);
}
}tr1;
struct node
{
int mx,sx;
node(){}
node(int mx,int sx):mx(mx),sx(sx){}
void ins(int x)
{
if(x>mx)sx=mx,mx=x;
else if(x>sx)sx=x;
}
};
node merge(node r1,node r2)
{
node ret=r1;
ret.ins(r2.mx);ret.ins(r2.sx);
return ret;
}
struct Sheep
{
queue<int>q;
int ch[N][2],size[N],root[N],fa[N],val[N],sz[N],bj[N];
int cnt,rt,fre,pre,tar;
node v[N],n1;
int ap()
{
if(!q.empty())
{
int t=q.front();q.pop();
ls(t)=rs(t)=size[t]=root[t]=fa[t]=val[t]=bj[t]=0;
v[t]=node(0,0);
return t;
}
return ++cnt;
}
int newnode(int x)
{
int ret=ap();bj[ret]=1;
val[ret]=x;size[ret]=sz[ret]=1;
v[ret]=node(x,0);
tr1.insert(root[ret],x,A,1);
return ret;
}
void pushup(int x)
{
size[x]=size[ls(x)]+size[rs(x)];
sz[x]=size[x]+1;
root[x]=tr1.merge(root[ls(x)],root[rs(x)]);
v[x]=merge(v[ls(x)],v[rs(x)]);
fa[ls(x)]=fa[rs(x)]=x;
}
int build(int l,int r)
{
if(l>r)return 0;
if(l==r)return newnode(a[l]);
int mid=(l+r)>>1,ret=ap();
ls(ret)=build(l,mid);
rs(ret)=build(mid+1,r);
pushup(ret);
return ret;
}
void dfs(int x)
{
if(!x)return;
q.push(x);tr1.del(root[x]);
if(bj[x]){a[++n]=val[x];return;}
dfs(ls(x));dfs(rs(x));
}
void reb(int x)
{
tr1.del(root[x]);
n=0;dfs(ls(x));dfs(rs(x));
int t=build(1,n);
if(x==rt)rt=t;
fa[t]=fa[x];
ch[fa[x]][which(x)]=t;
}
void insert(int &now,int x,int y)
{
if(size[now]==1||!now)
{
int t=newnode(y),ret=ap();
fa[ret]=pre;ls(ret)=t;rs(ret)=now;
pushup(ret);now=ret;
return;
}
pre=now;
if(size[ls(now)]>=x)insert(ls(now),x,y);
else insert(rs(now),x-size[ls(now)],y);
tr1.insert(root[now],y,A,1);
v[now].ins(y);size[now]++;sz[now]+=2;
fa[ls(now)]=fa[rs(now)]=now;
if(max(sz[ls(now)],sz[rs(now)])>sz[now]*alp)
fre=now;
}
void del(int &now,int x)
{
if(bj[now])
{q.push(now);tar=val[now];now=0;return;}
if(size[ls(now)]>=x)del(ls(now),x);
else del(rs(now),x-size[ls(now)]);
tr1.insert(root[now],tar,A,-1);
v[now]=merge(v[ls(now)],v[rs(now)]);
size[now]--;sz[now]--;
fa[ls(now)]=fa[rs(now)]=now;
if(max(sz[ls(now)],sz[rs(now)])>sz[now]*alp)
fre=now;
}
void insert(int x,int y)
{
fre=0;insert(rt,x,y);
if(fre)reb(fre);
}
void del(int x)
{
fre=0;del(rt,x);
if(fre)reb(fre);
}
void find(int now,int pre,int x,int y)
{
if(pre+1>=x&&pre+size[now]<=y)
{
st[++top]=root[now];
n1=merge(n1,v[now]);
return;
}
if(pre+size[ls(now)]>=x)
find(ls(now),pre,x,y);
if(pre+size[ls(now)]<y)
find(rs(now),pre+size[ls(now)],x,y);
}
node find(int x,int y)
{
top=0;n1=node(0,0);
find(rt,0,x,y);
return n1;
}
}tr2;
int main()
{
scanf("%d%d",&n,&m);n0=n;
for(int i=1;i<=n;i++)scanf("%d",&a[i]);
tr2.rt=tr2.build(1,n);
for(int x,y;m--;)
{
scanf("%s",s);
if(s[0]=='I')
{
scanf("%d%d",&x,&y);
x=(x+ans)%n0+1;y=(y+ans)%(1<<A);n0++;
tr2.insert(x,y);
}
else if(s[0]=='D')
{
scanf("%d",&x);
x=(x+ans)%n0+1;n0--;
tr2.del(x);
}
else if(s[0]=='C')
{
scanf("%d%d",&x,&y);
x=(x+ans)%n0+1;y=(y+ans)%(1<<A);
tr2.del(x);
tr2.insert(x,y);
}
else
{
scanf("%d%d",&x,&y);
x=(x+ans)%n0+1;y=(y+ans)%n0+1;
node t=tr2.find(x,y);
printf("%d\n",ans=tr1.query(t.sx,A));
}
}
return 0;
}

749

被折叠的 条评论
为什么被折叠?



