zoukankan      html  css  js  c++  java
  • 【BZOJ3110】K大数查询(整体二分)

    【BZOJ3110】K大数查询(整体二分)

    题面

    BZOJ

    题解

    看了很久整体二分
    一直不知道哪里写错了
    。。。
    又把树状数组当成线段树区间加法来用了。。

    整体二分还是要想清楚在干什么:
    我们考虑第(K)大是什么
    就是还有(K-1)个比他小
    这样子就可以考虑二分之后如何(check)
    当前二分出一个答案之后
    按照时间顺序检查每个操作
    如果是添加:
    如果加进去的值比二分的答案要小
    证明对结果没有贡献
    直接丢到左区间里不管
    否则线段树做区间加法
    如果是修改
    检查一下当前是否满足
    然后分类丢到左右区间

    总的来说
    想清楚还是挺容易的

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<set>
    #include<map>
    #include<vector>
    #include<queue>
    using namespace std;
    #define ll long long
    #define RG register
    #define MAX 52000
    #define lson (now<<1)
    #define rson (now<<1|1)
    inline int read()
    {
        RG int x=0,t=1;RG char ch=getchar();
        while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
        if(ch=='-')t=-1,ch=getchar();
        while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
        return x*t;
    }
    struct Node
    {
    	int clr;
    	int ly;
    	ll sum;
    	void clear(){clr=ly=sum=0;}
    }t[MAX<<3];
    int n,m,ans[MAX];
    void putlazy(int now,int l,int r,int w)
    {
    	t[now].sum+=w*(r-l+1);
    	t[now].ly+=w;
    }
    void clr(int now)
    {
    	if(t[now].clr)
    	{
    		t[lson].clear();
    		t[rson].clear();
    		t[lson].clr=1;
    		t[rson].clr=1;
    		t[now].clr=0;
    	}
    }
    void pushdown(int now,int l,int r)
    {
    	int mid=(l+r)>>1;
    	clr(now);
    	putlazy(lson,l,mid,t[now].ly);
    	putlazy(rson,mid+1,r,t[now].ly);
    	t[now].ly=0;
    }
    void Modify(int now,int l,int r,int L,int R)
    {
    	pushdown(now,l,r);
    	if(l==L&&r==R){putlazy(now,l,r,1);return;}
    	t[now].sum+=R-L+1;
    	int mid=(l+r)>>1;
    	if(R<=mid)Modify(lson,l,mid,L,R);
    	else if(L>mid)Modify(rson,mid+1,r,L,R);
    	else{Modify(lson,l,mid,L,mid);Modify(rson,mid+1,r,mid+1,R);}
    }
    ll Query(int now,int l,int r,int L,int R)
    {
    	pushdown(now,l,r);
    	if(L<=l&&r<=R)return t[now].sum;
    	int mid=(l+r)>>1;ll ret=0;
    	if(L<=mid)ret+=Query(lson,l,mid,L,R);
    	if(R>mid)ret+=Query(rson,mid+1,r,L,R);
    	return ret;
    }
    struct Ask{int opt,l,r,c,id;}p[MAX],p1[MAX],p2[MAX];
    void Work(int L,int R,int l,int r)
    {
    	if(L>R)return;
    	if(l==r)
    	{
    		for(int i=L;i<=R;++i)ans[p[i].id]=l;
    		return;
    	}
    	int mid=(l+r)>>1;
    	int t1=0,t2=0;
    	for(int i=L;i<=R;++i)
    	{
    		if(p[i].opt==1)
    		{
    			if(p[i].c<=mid)p1[++t1]=p[i];
    			else
    			{
    				p2[++t2]=p[i];
    				Modify(1,1,n,p[i].l,p[i].r);
    			}
    		}
    		else
    		{
    			ll ss=Query(1,1,n,p[i].l,p[i].r);
    			if(ss>=p[i].c)p2[++t2]=p[i];
    			else p[i].c-=ss,p1[++t1]=p[i];
    		}
    	}
    	for(int i=1;i<=t1;++i)p[L+i-1]=p1[i];
    	for(int i=1;i<=t2;++i)p[L+t1+i-1]=p2[i];
    	t[1].clear();t[1].clr=1;
    	Work(L,L+t1-1,l,mid);Work(L+t1,R,mid+1,r);
    }
    int main()
    {
    	n=read();m=read();
    	int sum=0;
    	for(int i=1;i<=m;++i)
    	{
    		p[i].opt=read();p[i].l=read();p[i].r=read();p[i].c=read();
    		if(p[i].opt==2)p[i].id=++sum;
    	}
    	Work(1,m,-n,n);
    	for(int i=1;i<=sum;++i)printf("%d
    ",ans[i]);
    	return 0;
    }
    
    
  • 相关阅读:
    JS 位数不够自动左补0
    oracle 不同表空间的数据迁移
    Vue 学习
    c# 之Web.config
    c# 之泛型
    WritableWorkbook操作Excel
    MIME类型
    Excel 批量出来数据
    Excel的用到的常规的技巧
    得到Xml中 元素的值
  • 原文地址:https://www.cnblogs.com/cjyyb/p/8414570.html
Copyright © 2011-2022 走看看