zoukankan      html  css  js  c++  java
  • 【JZOJ3379】查询

    description

    对于一个整数序列,查询区间第k大数可以在O(logN)的时间内轻松完成。现在我们对这个问题进行推广。

    考虑带重复数的集合(multiset)。定义在该类集合上的并操作“+”为两个集合的所有数不剔除重复得到的结果。比如,若A={1,2,2,3},B={2,3,4,4},则C={1,2,2,2,3,3,4,4}。

    对于一个给定序列A[1..N],定义A[x..y]为包含y-x+1个元素的集合{A[x],A[x+1],…,A[y]}。现在,给定整数序列A,你需要回答很多询问,其中第i个询问要求集合A[x[i,1]..y[i,1]]+A[x[i,2]..y[i,2]]+…+A[x[i,ki]..y[i,ki]]中第pi小的元素。


    analysis

    • 一年的时间使我变成了主席树傻子

    • 一个区间当然可以直接主席树做,五个区间其实也可以

    • (a)的值并不是很大,不需要离散化

    • 对于当前查询,可以求出五个区间左儿子区间里面数的个数之和,然后和查询值比较

    • 然后向左或右儿子继续二分,把五个区间也向左或向右挪就好

    • 主席树是真的虚,一定一定要多做点题,巩固老知识,才能更好学习新知识


    code

    #pragma GCC optimize("O3")
    #pragma G++ optimize("O3")
    #include<stdio.h>
    #include<string.h>
    #include<algorithm>
    #define MAXN 200005
    #define MAX 1000005
    #define ll long long
    #define fo(i,a,b) for (ll i=a;i<=b;++i)
    #define fd(i,a,b) for (ll i=a;i>=b;--i)
    
    using namespace std;
    
    ll lson[MAX*20],rson[MAX*20],sum[MAX*20];
    ll a[MAXN],root[MAXN];
    ll n,m,mx,k,p,tot;
    ll L[10],R[10];
    
    inline ll read()
    {
    	ll x=0,f=1;char ch=getchar();
    	while (ch<'0' || '9'<ch){if (ch=='-')f=-1;ch=getchar();}
    	while ('0'<=ch && ch<='9')x=x*10+ch-'0',ch=getchar();
    	return x*f;
    }
    inline void build(ll &t,ll l,ll r)
    {
    	t=++tot;
    	if (l==r)return;
    	ll mid=(l+r)>>1;
    	build(lson[t],l,mid),build(rson[t],mid+1,r);
    }
    inline void modify(ll old,ll &t,ll l,ll r,ll x)
    {
    	t=++tot;
    	lson[t]=lson[old],rson[t]=rson[old],sum[t]=sum[old];
    	if (l==r){++sum[t];return;}
    	ll mid=(l+r)>>1;
    	if (x<=mid)modify(lson[old],lson[t],l,mid,x);
    	else modify(rson[old],rson[t],mid+1,r,x);
    	sum[t]=sum[lson[t]]+sum[rson[t]];
    }
    inline ll query(ll l,ll r,ll x)
    {
    	if (l==r)return l;
    	ll mid=(l+r)>>1,tmp=0;
    	fo(i,1,k)tmp+=sum[lson[R[i]]]-sum[lson[L[i]]];
    	if (x<=tmp)
    	{
    		fo(i,1,k)L[i]=lson[L[i]],R[i]=lson[R[i]];
    		return query(l,mid,x);
    	}
    	else
    	{
    		fo(i,1,k)L[i]=rson[L[i]],R[i]=rson[R[i]];
    		return query(mid+1,r,x-tmp);
    	}
    }
    int main()
    {
    	freopen("T3.in","r",stdin);
    	n=read(),m=read();
    	fo(i,1,n)a[i]=read();
    	build(root[0],0,1000000);
    	fo(i,1,n)modify(root[i-1],root[i],0,1000000,a[i]);
    	while (m--)
    	{
    		k=read(),p=read();
    		fo(i,1,k)L[i]=root[read()-1],R[i]=root[read()];
    		printf("%lld
    ",query(0,1000000,p));
    	}
    	return 0;
    }
    
  • 相关阅读:
    155. 最小栈
    160. 相交链表
    PAT 1057 Stack
    PAT 1026 Table Tennis
    PAT 1017 Queueing at Bank
    PAT 1014 Waiting in Line
    PAT 1029 Median
    PAT 1016 Phone Bills
    PAT 1010 Radix
    PAT 1122 Hamiltonian Cycle
  • 原文地址:https://www.cnblogs.com/horizonwd/p/11165296.html
Copyright © 2011-2022 走看看