jzoj3379 query [chairman tree]

Topic

The main idea of the topic

In this paper, we give an ordered set AAA, define Al, RA {l, R} Al, R} to represent the number in the range of l ∼ rl\sim rl ∼ r in the set.

Define addition A+BA+BA+B to represent all elements in two sets (without de duplication).

Now, every time I ask ki,pik_i,p_iki, pi, I give kik_iki intervals [L J, rj] [l_j, r_j] [LJ, rj]
Find ∑ J = 1kialj, rj \ sum {J = 1} ^ {K {I} a {Luj, R {J} J = 1 ∑ ki {Alj, rj}
The number of pips in this set that are smaller than IPI.

Solving problems

Because k ≤ 5k\leq 5k ≤ 5, we can consider the general chairman tree to find the kkk of the interval is small.

Now for LJ, rj l_j, R J J, RJJ of each query, we let the kkk group subscript run on the chairman number at the same time. Then the number of numbers per time is the sum of the numbers calculated by the subscript of kkk group. Then moving left or right is to let 555 groups move at the same time.

codecodecode

#include<cstdio>
#include<algorithm>
#define MN 201000
using namespace std;
struct tnode{
    int w,l,r,ls,rs;
}t[MN<<5];
int n,m,x,y,k,a[MN],b[MN],root[MN],q,w,r[6],l[6],qnum,cnt;
int build(int l,int r)
{
    int k=++cnt;
    t[k].l=l,t[k].r=r;
    if (l==r) return k;
    int mid=(l+r)>>1;
    t[k].ls=build(l,mid);
    t[k].rs=build(mid+1,r);
    return k;
}
int addt(int k,int z)
{
    int nb=++cnt;
    t[nb]=t[k];t[nb].w++;
    if (t[k].l==z&&t[k].r==z) return nb;
    int mid=(t[k].l+t[k].r)>>1;
    if (z<=mid) t[nb].ls=addt(t[k].ls,z);
    else t[nb].rs=addt(t[k].rs,z);
    return nb;
}
int query(int k)
{
    if (t[r[1]].l==t[r[1]].r) return t[r[1]].l;
    int num=0;
    for(int i=1;i<=qnum;i++)
    	num+=t[t[r[i]].ls].w-t[t[l[i]].ls].w;
    if(k<=num){
    	for(int i=1;i<=qnum;i++)
    		r[i]=t[r[i]].ls,l[i]=t[l[i]].ls;
    	return query(k);
	}
	else{
		for(int i=1;i<=qnum;i++)
    		r[i]=t[r[i]].rs,l[i]=t[l[i]].rs;
    	return query(k-num);
	}
}
int main()
{
    scanf("%d%d",&n,&m);
    for (int i=1;i<=n;i++)
      scanf("%d",&a[i]),b[i]=a[i];
    sort(b+1,b+1+n);
    int q=unique(b+1,b+1+n)-b-1;
    root[0]=build(1,q);
    for (int i=1;i<=n;i++)
    {
      int te=lower_bound(b+1,b+1+q,a[i])-b;
      root[i]=addt(root[i-1],te);
    }
    for (int i=1;i<=m;i++)
    {
        scanf("%d%d",&qnum,&k);
        for(int j=1;j<=qnum;j++)
        	scanf("%d%d",&l[j],&r[j]),l[j]=root[l[j]-1],r[j]=root[r[j]];
        printf("%d\n",b[query(k)]);
    }
}

Posted by szcieder on Fri, 01 Nov 2019 13:54:40 -0700