• P2468 [SDOI2010]粟粟的书架


    题目

    P2468 [SDOI2010]粟粟的书架

    我*做个**题目花了一个小时??

    奔着主席树标签来的,(n=1)裸的主席树,(n,m≤200)裸的容斥(dalao们也可以去打一遍二维主席树)

    容斥打了三遍才过,主席树查询竟然先去查询较小值??今天状态不好o(╥﹏╥)o

    做法

    (n,m≤200)是经典的容斥,大家应该都见过吧,预处理(num_{i,j,k})为前(i)(j)(≥k)的个数,同理(sum_{i,j,k})为前缀
    剩下的是二分也不用多说了(O(qlog max{a_i}))

    (n=1)这部分卡容斥的空间,主席树预处理值域区间个数及和(O(qlog max{a_i}))

    My complete code

    #include<cstdio>
    #include<iostream>
    #include<string>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    typedef int LL;
    const int inf=2000000001;
    //const int maxn=2000000;
    inline LL Read(){
    	LL x(0),f(1);char c=getchar();
    	while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
    	while(c>='0'&&c<='9')x=(x<<3)+(x<<1)+c-'0',c=getchar();
    	return x*f;
    }
    LL n,m,q,Mi=inf,Mx=-inf,nod;
    LL sum[209][209][1009],num[209][209][1009],a[209][209],b[500009],root[500009];
    struct Tree{
    	LL son[2],size,sum;
    }T[20000009];
    void Update(LL &now,LL pre,LL l,LL r,LL c){
    	now=++nod;
    	T[now].size=T[pre].size+1;
    	T[now].sum=T[pre].sum+c;
    	if(l==r)
    	    return;
    	LL mid(l+r>>1);
    	if(c<=mid){
    	    Update(T[now].son[0],T[pre].son[0],l,mid,c);
    	    T[now].son[1]=T[pre].son[1];
    	}else{
    		Update(T[now].son[1],T[pre].son[1],mid+1,r,c);
    	    T[now].son[0]=T[pre].son[0];
    	}
    }
    LL Query(LL now,LL pre,LL l,LL r,LL val){
    	if(l==r){
    		return ceil((double)val/l);
    	}
    	LL mid(l+r>>1),ret=T[T[now].son[1]].sum-T[T[pre].son[1]].sum;
    	if(ret>=val)
    	    return Query(T[now].son[1],T[pre].son[1],mid+1,r,val);
    	else
    	    return (T[T[now].son[1]].size-T[T[pre].son[1]].size)+
    		        Query(T[now].son[0],T[pre].son[0],l,mid,val-ret);
    }
    int main(){
    	n=Read(),m=Read(),q=Read();
    	if(n==1){
    		for(LL i=1;i<=m;++i){
    			LL now(Read());
    			Mi=min(Mi,now),Mx=max(Mx,now);
    			b[i]=b[i-1]+now;
    		}
    		for(LL i=1;i<=m;++i)
    			Update(root[i],root[i-1],Mi,Mx,b[i]-b[i-1]);
    		while(q--){
    			LL xl(Read()),l(Read()),xr(Read()),r(Read()),x(Read());
    			if(b[r]-b[l-1]<x){
    				printf("Poor QLW
    ");
    				continue;
    			}
    			printf("%d
    ",Query(root[r],root[l-1],Mi,Mx,x));
    		}
    	}else{
    		for(LL i=1;i<=n;++i){
    			for(LL j=1;j<=m;++j){
    			    a[i][j]=Read();
    			    Mi=min(Mi,a[i][j]),Mx=max(Mx,a[i][j]);
    			}
    		}
    		for(LL i=1;i<=n;++i){
    			for(LL j=1;j<=m;++j){
    				for(LL k=Mx;k>=Mi;--k){
    					num[i][j][k]=(num[i-1][j][k]+num[i][j-1][k]-num[i-1][j-1][k])+(a[i][j]>=k?1:0);
    					sum[i][j][k]=(sum[i-1][j][k]+sum[i][j-1][k]-sum[i-1][j-1][k])+(a[i][j]>=k?a[i][j]:0);
    				}
    			}
    		}
    		while(q--){
    			LL xl(Read()),yl(Read()),xr(Read()),yr(Read()),x(Read()),ret,ans(0);
    			LL l=Mi,r=Mx;
    			if((sum[xr][yr][l]-sum[xr][yl-1][l]-sum[xl-1][yr][l]+sum[xl-1][yl-1][l])<x){
    				printf("Poor QLW
    ");
    				continue;
    			}
    			while(l<=r){
    				LL mid(l+r>>1);
    				if((sum[xr][yr][mid]-sum[xr][yl-1][mid]-sum[xl-1][yr][mid]+sum[xl-1][yl-1][mid])>=x){
    					ret=mid;
    					l=mid+1;
    				}else
    				    r=mid-1;
    			}
    			++ret;
    			x-=(sum[xr][yr][ret]-sum[xr][yl-1][ret]-sum[xl-1][yr][ret]+sum[xl-1][yl-1][ret]);
    			ans+=(num[xr][yr][ret]-num[xr][yl-1][ret]-num[xl-1][yr][ret]+num[xl-1][yl-1][ret]);
    			ans+=ceil((double)x/(ret-1));
    			printf("%d
    ",ans);
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    HDU 1863 畅通工程
    基于Platinum库的DMS实现(android)
    编写一个程序,输入月份号,输出该月的中文名和英文名。
    Android系统移植与调试之------->如何修改Android设备的开机第一阶段Logo
    利用面向对象解母牛生小牛问题
    Java String.replace()方法
    Android系统移植与调试之------->如何修改Android设备的开机第二阶段Logo
    Linux网络设备驱动架構學習(三)
    把给定的字符串解析为Date对象
    git使用三把斧
  • 原文地址:https://www.cnblogs.com/y2823774827y/p/10307751.html
Copyright © 2020-2023  润新知