• P1533可怜的狗狗


    困死了,完全做不下去题
    就当是对莫队最最基本的思想的一个复习叭(只有最最基本的思想,没有莫队)
    传送
    我们可以很容易的想到这题要用线段树。

    60pts

    此题要求某个区间里第K小的数,可以暴力的考虑对每个节点所对应的区间排序。这里排序一次可以最快(O(n)),查询时也要排序,所以查询一次是(O(nlogn)),总复杂度就是(O(nmlogn))。不吸氧60pts。(可能还不如朴素?)

    100pts

    既然普通线段树不行,那咱就用权值线段树搞搞试试。权值线段树上维护每一个数出现的次数。先离散化,查询时往里扔点,删点即可。题目没有修改,考虑离线做法。我们可以参照莫队的思想,把所有询问的区间记录下来,以左端点为第一关键字,右端点为第二关键字排序。同时设置两个指针l,r,指向上一个处理的区间。当r<当前要处理的区间时,就不断向右移,同时把经过的点扔进权值线段树里。l同理,不过是把经过的点从线段树里删除。每处理完一个区间,就把查询的结果扔进ans数组里,最后输出ans数组即可。
    因为题目保证查询的区间互不包含,所以r最多向右移n次,l最多向右移n次,修改与查询都是logn,总复杂度就是(O(nlogn))
    突然奇想用树状数组会不会更快?

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    #include<queue>
    #include<map>
    #include<vector>
    #define pa pair<int,int>
    using namespace std;
    typedef long long ll;
    inline int read()
    {
    	char ch=getchar();
    	int x=0;bool f=0;
    	while(ch<'0'||ch>'9')
    	{
    		if(ch=='-')f=1;
    		ch=getchar();
    	}
    	while(ch>='0'&&ch<='9')
    	{
    		x=(x<<3)+(x<<1)+(ch^48);
    		ch=getchar();
    	}
    	return f?-x:x;
    }
    const int N=3000001;
    int n,m,be[N],ae[N],t,ans[50001],l=1,r,sum[4*N];
    struct Q{
    	int l,r,k,id;//记录查询的区间与查询的顺序
    }q[50001];
    int lower_bound(int kkk)//手写离散化qwq
    {
    	int ll=1,rr=t;
    	while(ll<=rr)
    	{
    		int mid=(ll+rr)>>1;
    		if(ae[mid]==kkk) return mid;
    		if(ae[mid]>kkk)rr=mid-1;
    		else ll=mid+1;
    	}
    	if(ae[ll]>kkk)ll--;//写丑了.jpg
    	return ll;
    }
    void modi(int k,int l,int r,int x,int v)
    {
    	if(l==r&&l==x)
    	 {sum[k]+=v;return ;}
    	int mid=(l+r)>>1;
    	if(x<=mid) modi(k<<1,l,mid,x,v);
    	else modi(k<<1|1,mid+1,r,x,v);
    	sum[k]=sum[k<<1]+sum[k<<1|1]; 
    }
    int qry(int k,int l,int r,int rk)
    {
    	if(l==r&&sum[k]==rk)
    		return l;
    	int mid=(l+r)>>1;
    	int rtn;
    	if(sum[k<<1]>=rk) rtn=qry(k<<1,l,mid,rk);
    	else rtn=qry(k<<1|1,mid+1,r,rk-sum[k<<1]);
    	return rtn; 	
    }
    bool cmp(Q a,Q b)
    {
    	if(a.l!=b.l) return a.l<b.l;
        return a.r<b.r;
    }
    int main()
    {
       n=read();m=read();
       for(int i=1;i<=n;i++)
       {
       	be[i]=read();ae[i]=be[i];
       }
       sort(ae+1,ae+1+n);
       t=unique(ae+1,ae+1+n)-ae-1;
       for(int i=1;i<=n;i++)
        be[i]=lower_bound(be[i]);
       for(int i=1;i<=m;i++)//丑陋的手写离散化
        q[i].l=read(),q[i].r=read(),q[i].k=read(),q[i].id=i;
       sort(q+1,q+m+1,cmp);
       for(int i=1;i<=m;i++)
       {
       	while(r<q[i].r)
       	  modi(1,1,t,be[++r],1);
            while(l<q[i].l)
              modi(1,1,t,be[l++],-1); //注意是l++,不是++l
            ans[q[i].id]=qry(1,1,t,q[i].k); 
       }    
       for(int i=1;i<=m;i++)
        printf("%d
    ",ae[ans[i]]);//记得在离散化后还原回去
    }
    
  • 相关阅读:
    报到开博随笔
    为Windows2008升级系统补丁
    String:本质上是字符数组
    为Windows2008服务器安装.NET Framework 3.0
    设计ShartPoint的组织结构和成员
    中文:一个面向对象的自然语言
    从一个帖子看部分大学生的学习心态
    Enum:枚举
    Array:一组数据的有序集合
    部署SQL Server2008企业版
  • 原文地址:https://www.cnblogs.com/lcez56jsy/p/11778019.html
Copyright © 2020-2023  润新知