社区讨论
一个奇怪的想法,本来应该T,但是RE了?
P3834【模板】可持久化线段树 2参与者 2已保存回复 3
讨论操作
快速查看讨论及其快照的属性,并进行相关操作。
- 当前回复
- 3 条
- 当前快照
- 1 份
- 快照标识符
- @lo1ul4fc
- 此快照首次捕获于
- 2023/10/23 03:14 2 年前
- 此快照最后确认于
- 2023/11/03 03:45 2 年前
一颗
CPPFhq Treap ,莫队思想,只是乱搞,勿喷#include<bits/stdc++.h> // 莫队 + FHQ Treap 实现静态区间第k小问题
#define Ls(x) tree[(x)].ls
#define Rs(x) tree[(x)].rs
#define ll long long
using namespace std;
const int N=5e5+7;
struct query
{
int l,r,k,id;
}q[N];
int n,m,a[N],block;
ll ans[N],res;
class Fhq_Treap //友善的Fhq Treap
{
private:
struct Node
{
int pri,ls,rs,siz,key;
}tree[N];
int Total,Root;
void pushup(int x)
{
if(!x)
return;
tree[x].siz=tree[Ls(x)].siz+tree[Rs(x)].siz+1;
return;
}
int create(int x)
{
int rt=++Total;
tree[rt]={rand(),0,0,1,x};
return rt;
}
void Split(int x,int key,int &L,int &R)
{
if(!x)
{
L=R=0;
return;
}
if(tree[x].key<=key)
{
L=x;
Split(Rs(x),key,Rs(x),R);
}
else
{
R=x;
Split(Ls(x),key,L,Ls(x));
}
pushup(x);
return;
}
int Merge(int x,int y)
{
if(!x||!y)
return x+y;
if(tree[x].pri>tree[y].pri)
{
Rs(x)=Merge(Rs(x),y);
pushup(x);
return x;
}
else
{
Ls(y)=Merge(x,Ls(y));
pushup(y);
return y;
}
}
public:
void Insert(int key)
{
int x,y;
Split(Root,key-1,x,y);
Root=Merge(Merge(x,create(key)),y);
return;
}
void Remove(int key)
{
int x,y,z;
Split(Root,key,x,z);
Split(x,key-1,x,y);
if(y)
y=Merge(Ls(y),Rs(y));
Root=Merge(Merge(x,y),z);
return;
}
int Kth(int k)
{
int x=Root;
for(;;)
{
if(tree[Ls(x)].siz+1==k)
break;
else if(tree[Ls(x)].siz+1>k)
x=Ls(x);
else
{
k-=tree[Ls(x)].siz+1;
x=Rs(x);
}
}
return tree[x].key;
}
};
Fhq_Treap treap;
inline bool cmp(query x,query y)
{
if((x.l-1)/block==(y.l-1)/block)
return x.r<y.r;
return x.l/block<y.l/block;
}
inline void ins(int x)
{
treap.Insert(x);
return;
}
inline void del(int x)
{
treap.Remove(x);
return;
}
int main()
{
srand(time(0));
scanf("%d%d",&n,&m);
block=sqrt(n);
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
}
for(int i=1,l,r,k;i<=m;i++)
{
scanf("%d%d%d",&l,&r,&k);
q[i]={l,r,k,i};
}
sort(q+1,q+1+m,cmp); //莫队排序
// for(int i=1;i<=n;i++)
// {
// treap.Insert(a[i]);
// }
// for(int i=1;i<=n;i++)
// {
// printf("%d\n",a[treap.kth(treap.root,i)]);
// }
int L=q[1].l,R=q[1].r;
for(int i=L;i<=R;i++)
{
ins(a[i]);
}
// printf("First L is : %d\n First R is : %d\n",L,R);
// for(int i=1;i<=m;i++)
// {
// printf("%d %d %d %d\n",q[i].l,q[i].r,q[i].k,q[i].id);
// }
ans[q[1].id]=treap.Kth(q[1].k); //先查了第一询问作为初始端点
for(int i=2;i<=m;i++)
{
int l=q[i].l,r=q[i].r;
// printf("%d %d %d %d\n",l,r,q[i].k,q[i].id);
while(L>l)
{
ins(a[--L]);
}
while(R<r)
{
ins(a[++R]);
}
while(L<l)
{
del(a[L++]);
}
while(R>r)
{
del(a[R--]);
}
ans[q[i].id]=treap.Kth(q[i].k);
}
for(int i=1;i<=m;i++)
{
printf("%lld\n",ans[i]);
}
return 0;
}
悬关
回复
共 3 条回复,欢迎继续交流。
正在加载回复...