您的位置:首页 > 产品设计 > UI/UE

5296. 【清华集训2017模拟】Sequence 树套树

2017-08-20 16:01 381 查看
题意:给你一些二元组如(ai,bi),每次询问l,r,x,y,k.

先把元素按照第一关键字排序,取出其中排名为x,y的,按照第二关键字排序后取出排名为k的元素。

树套树很明显了其实。。

对于第一个操作,我们对于a维护一颗主席树,取出第x,y的端点,然后在外层主席树中把第x到y中的节点信息取出来然后做个线段树区间k大就好了。。

#include<cstdio>
#include<algorithm>
#include<cstring>
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define fd(i,a,b) for(int i=a;i>=b;i--)
using namespace std;
const int N=3e5+5;
int n,m,sz,tot,root
;
struct node
{
int x,y;
}a
,b
;
struct tree
{
int l,r,s,root;
}t[N*30];
inline void ins(int &x,int y,int l,int r,int v)
{
x=++sz;
t[x]=t[y];
t[x].s++;
if (l==r)return;
int mid=(l+r)/2;
if (v<=mid)ins(t[x].l,t[y].l,l,mid,v);
else ins(t[x].r,t[y].r,mid+1,r,v);
}
inline void ins(int &x,int y,int l,int r,int v1,int v2)
{
x=++sz;
t[x]=t[y];
t[x].s++;
ins(t[x].root,t[y].root,1,n,v2);
if (l==r)return;
int mid=(l+r)>>1;
if (v1<=mid)ins(t[x].l,t[y].l,l,mid,v1,v2);
else ins(t[x].r,t[y].r,mid+1,r,v1,v2);
}
inline int kth(int x,int y,int l,int r,int k)
{
if (l==r)return l;
int mid=(l+r)>>1;
if (t[t[x].l].s-t[t[y].l].s>=k)return kth(t[x].l,t[y].l,l,mid,k);
else return kth(t[x].r,t[y].r,mid+1,r,k-t[t[x].l].s+t[t[y].l].s);
}
inline void get(int x,int y,int l,int r,int l1,int r1)
{
if (l1>r1)return;
if (l==l1&&r==r1)
{
tot++;
b[tot].x=t[x].root;
b[tot].y=t[y].root;
return;
}
int mid=(l+r)/2;
get(t[x].l,t[y].l,l,mid,l1,min(r1,mid));
get(t[x].r,t[y].r,mid+1,r,max(l1,mid+1),r1);
}
inline int solve(int l,int r,int x,int y,int k)
{
x=kth(root[r],root[l-1],1,n,x);
y=kth(root[r],root[l-1],1,n,y);
tot=0;
get(root[r],root[l-1],1,n,x,y);
l=1,r=n;
while (l<r)
{
int mid=(l+r)>>1,s=0;
fo(i,1,tot)s+=t[t[b[i].x].l].s-t[t[b[i].y].l].s;
if (s>=k)
{
fo(i,1,tot)b[i].x=t[b[i].x].l,b[i].y=t[b[i].y].l;
r=mid;
}
else
{
fo(i,1,tot)
{
k-=t[t[b[i].x].l].s-t[t[b[i].y].l].s;
b[i].x=t[b[i].x].r;
b[i].y=t[b[i].y].r;
}
l=mid+1;
}
}
return l;
}
int main()
{
freopen("sequence.in","r",stdin);
freopen("sequence.out","w",stdout);
scanf("%d",&n);
fo(i,1,n)scanf("%d",&a[i].x);
fo(i,1,n)scanf("%d",&a[i].y);
fo(i,1,n)ins(root[i],root[i-1],1,n,a[i].x,a[i].y);
scanf("%d",&m);
while (m--)
{
int l,r,x,y,k;
scanf("%d%d%d%d%d",&l,&r,&
4000
amp;x,&y,&k);
printf("%d\n",solve(l,r,x,y,k));
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: