【BZOJ】1926: [Sdoi2010]粟粟的书架(暴力+主席树)

题目

传送门:QWQ

 

 

分析

两道题目

第一问暴力预处理

用$ a[i][j][k] $和$ s[i][j][k] $ 表示从$ (1,1) $ 到 $ (i,j) $ 这个矩形中比k大的数的个数和这些数的和。

对于询问我们二分k,得出答案(最后还要减掉一些值一样的东西 详见代码)

第二问主席树

r=1时只有一个数列,我们要求的是用多少数可以大于等于h

用主席树搞,询问时就像询问区间第k大时一样向左向右走,只不过要再套个二分。 

 

 

代码

#include <bits/stdc++.h>
using namespace std;
const int maxn=501000;
int s[205][205][1005],a[205][205][1005],p[205][205];
  int rt[maxn], newp, ls[11000000], rs[11000000], sum[11000000], v[11000000];
//int rt[maxn], newp, ls[10000100], rs[10000100], sum[10000100], v[10000100];

int r,c,m;
inline int in()  
{  
    char c=getchar();int x=0;  
    while (c<'0'||c>'9') c=getchar();  
    while (c>='0'&&c<='9') x=x*10+c-'0',c=getchar();  
    return x;  
}  
void insert(int l,int r,int x,int &cur,int cur1){
    cur=++newp;
    ls[cur]=ls[cur1]; rs[cur]=rs[cur1];
    sum[cur]=sum[cur1]+x; v[cur]=v[cur1]+1;
    if(l==r) return;
    int mid=l+r>>1;
    if(x<=mid) /*ls[cur]=ls[cur1],*/insert(l,mid,x,ls[cur],ls[cur1]);
    else /*rs[cur]=rs[cur1],*/insert(mid+1,r,x,rs[cur],rs[cur1]); 
}
int query(int x,int y,int h)
{
    x=rt[x-1];y=rt[y];
    if(sum[y]-sum[x]<h) return -1;
    int l=1,r=1000,ans=0;
    while(l<r){
        int mid=(l+r)>>1;
        if(sum[rs[y]]-sum[rs[x]]<h){
            ans+=v[rs[y]]-v[rs[x]]; h-=sum[rs[y]]-sum[rs[x]]; x=ls[x]; y=ls[y]; r=mid;
        //    printf("-----  %d\n",v[rs[y]]-v[rs[x]]);
        }
        else {
            l=mid+1; x=rs[x]; y=rs[y];
        }                                                                     
    }
    ans+=(h+l-1)/l;
    return ans;
}
int main()
{
    r=in();c=in();m=in();
    if(r!=1){
        for(int i=1;i<=r;i++)
        for(int j=1;j<=c;j++) p[i][j]=in();
        for(int i=1;i<=r;i++) 
        for(int j=1;j<=c;j++)
        for(int k=1;k<=1000;k++)
        {
            a[i][j][k]=a[i-1][j][k]+a[i][j-1][k]-a[i-1][j-1][k];
            s[i][j][k]=s[i-1][j][k]+s[i][j-1][k]-s[i-1][j-1][k];
            if(p[i][j]>=k){
                a[i][j][k]++; s[i][j][k]+=p[i][j];
            }
        }
        while(m--){
            int x1=in(),y1=in(),x2=in(),y2=in(),h=in();    
            int l=0,r=1001,ans; x1--;y1--;
            while(l+1<r){
                int mid=(l+r)>>1;ans=s[x2][y2][mid]-s[x2][y1][mid]-s[x1][y2][mid]+s[x1][y1][mid];
                if(ans>=h) l=mid; else r=mid;
            }
            int sum1=a[x2][y2][l]-a[x2][y1][l]-a[x1][y2][l]+a[x1][y1][l],
                sum2=s[x2][y2][l]-s[x2][y1][l]-s[x1][y2][l]+s[x1][y1][l];
            if(l==0){puts("Poor QLW"); continue;}
            else printf("%d\n",sum1-(sum2-h)/l);
        }
    }
    else{
        for(int i=1;i<=c;i++){
            int t=in();
            insert(1,1000,t,rt[i],rt[i-1]);
        }
        while(m--){
            int x1=in(),y1=in(),x2=in(),y2=in(),h=in();    
            int ans=query(y1,y2,h);
            if(ans==-1) puts("Poor QLW");
            else printf("%d\n",ans);
        }
    }
    return 0;
}

 

 

 

posted @ 2018-06-12 21:49  noble_(noblex)  阅读(...)  评论(...编辑  收藏
/* */