• 模板—算法—整体二分(区间k小值)


    模板—算法—整体二分(区间k小值)

    Code:

    #include <cstdio>
    #include <algorithm>
    using namespace std;
    #define N 200010
    int num[N],number[N],tmp[N],ans[N],n,m,id[N];
    struct Ask {int l,r,id,k;}ask[N],ask1[N],ask2[N];
    void change(int x,int y) {while(x<=n) tmp[x]+=y,x+=x&-x;}
    int find(int x) {int sum=0;while(x) sum+=tmp[x],x-=x&-x;return sum;}
    bool cmp(const int &a,const int &b) {return num[a]<num[b];}
    int find_ord(int x)
    {
    	int l=1,r=n+1;
    	while(l<r)
    	{
    		int mid=(l+r)>>1;
    		if(number[mid]>=x) r=mid;
    		else l=mid+1;
    	} return l;
    }
    void solve(int l,int r,int tl,int tr)
    {
    	if(l==r) {for(int i=tl;i<=tr;i++) ans[ask[i].id]=number[l]/*,printf("%d %d
    ",ask[i].id,l)*/;return;}
    	for(int i=l;i<=(l+r)>>1;i++) change(id[i],1); int top1=0,top2=0;
    	for(int i=tl;i<=tr;i++)
    		if(find(ask[i].r)-find(ask[i].l-1)>=ask[i].k) ask1[++top1]=ask[i];
    		else ask2[++top2]=ask[i],ask2[top2].k-=find(ask[i].r)-find(ask[i].l-1);
    	for(int i=1;i<=top1;i++) ask[tl+i-1]=ask1[i];
    	for(int i=1;i<=top2;i++) ask[tl+top1+i-1]=ask2[i];
    	for(int i=l;i<=(l+r)>>1;i++) change(id[i],-1);
    	solve(l,(l+r)>>1,tl,tl+top1-1),solve(((l+r)>>1)+1,r,tl+top1,tr);
    }
    int main()
    {
    	scanf("%d%d",&n,&m);
    	for(int i=1;i<=n;i++) scanf("%d",&num[i]),number[i]=num[i],id[i]=i;
    	sort(number+1,number+n+1),sort(id+1,id+n+1,cmp);
    	for(int i=1;i<=n;i++) num[i]=find(num[i]);
    	for(int i=1;i<=m;i++) scanf("%d%d%d",&ask[i].l,&ask[i].r,&ask[i].k),ask[i].id=i;
    	solve(1,n,1,m);
    	for(int i=1;i<=m;i++) printf("%d
    ",ans[i]);
    }
    

      

  • 相关阅读:
    public static void Invoke (Action action)
    C#编写WIN32系统托盘程序
    C#的互操作性:缓冲区、结构、指针
    SQLServer异步调用,批量复制
    Python体验(10)-图形界面之计算器
    Python体验(09)-图形界面之Pannel和Sizer
    Python体验(08)-图形界面之工具栏和状态栏
    Python体验(07)-图形界面之菜单
    C#利用WIN32实现按键注册
    Javascript猜数字游戏
  • 原文地址:https://www.cnblogs.com/yangsongyi/p/10656895.html
Copyright © 2020-2023  润新知