zoukankan      html  css  js  c++  java
  • bzoj1926: [Sdoi2010]粟粟的书架

    题目链接

    传送门

    题解

    大佬好强

    看了看数据范围,不是很明白为什么明明两道题却硬要挤在一道题里

    0.5倍经验orz……

    前一半的数据$R,C<=200$

    前缀和+二分

    $num[i][j][k]表示(1,1)到(i,j)中比大于等于k的数有几个$
    $sum[i][j][k]表示(1,1)到(i,j)中比大于等于k的数的总和$

    二分找k+1,对k直接暴力填

    后一半的数据就是个序列

    直接开个主席树

    二分一下取多少本书

    然后直接树上跑一跑就行

    ps:主席树查询时应优先挑选高度更高的书,原因应该不用解释

      1 // luogu-judger-enable-o2
      2 //minamoto
      3 #include<bits/stdc++.h>
      4 using namespace std;
      5 #define getc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
      6 char buf[1<<21],*p1=buf,*p2=buf;
      7 template<class T>inline bool cmax(T&a,const T&b){return a<b?a=b,1:0;}
      8 inline int read(){
      9     #define num ch-'0'
     10     char ch;bool flag=0;int res;
     11     while(!isdigit(ch=getc()))
     12     (ch=='-')&&(flag=true);
     13     for(res=num;isdigit(ch=getc());res=res*10+num);
     14     (flag)&&(res=-res);
     15     #undef num
     16     return res;
     17 }
     18 int n,m,q;
     19 namespace solve1{
     20     #define N 205
     21     int a[N][N],num[N][N][1005],sum[N][N][1005];
     22     int mx=0;
     23     int getsum(int a,int b,int c,int d,int h){
     24         return sum[c][d][h]-sum[c][b][h]-sum[a][d][h]+sum[a][b][h];
     25     }
     26     int getnum(int a,int b,int c,int d,int h){
     27         return num[c][d][h]-num[c][b][h]-num[a][d][h]+num[a][b][h];
     28     }
     29     int getans(int a,int b,int c,int d,int k,int need){
     30         int res=getnum(a,b,c,d,k+1);
     31         need-=getsum(a,b,c,d,k+1);
     32         if(need>=0){
     33             int num=need/k;
     34             res+=num;
     35             need-=num*k;
     36             if(need>0) ++res,need-=k;
     37         }
     38         return res;
     39     }
     40     bool check(int a,int b,int c,int d,int mid,int h){
     41         return getsum(a,b,c,d,mid)>h?1:0;
     42     }
     43     void main(){
     44         for(int i=1;i<=n;++i)
     45         for(int j=1;j<=m;++j)
     46         cmax(mx,a[i][j]=read());
     47         for(int k=0;k<=mx;++k)
     48         for(int i=1;i<=n;++i)
     49         for(int j=1;j<=m;++j){
     50             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);
     51             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);
     52         }
     53         while(q--){
     54             int a,b,c,d,h;
     55             a=read(),b=read(),c=read(),d=read(),h=read();
     56             --a,--b;
     57             if(getsum(a,b,c,d,0)<h){
     58                 puts("Poor QLW");continue;
     59             }
     60             int l=1,r=mx,ans=0;
     61             while(l<=r){
     62                 int mid=(l+r)>>1;
     63                 if(check(a,b,c,d,mid,h)) ans=mid,l=mid+1;
     64                 else r=mid-1;
     65             }
     66             if(!ans) ans=1;
     67             printf("%d
    ",getans(a,b,c,d,ans,h));
     68         }
     69     }
     70     #undef N
     71 }
     72 namespace solve2{
     73     #define N 500005
     74     int sum[N<<4],L[N<<4],R[N<<4],sz[N<<4];
     75     int rt[N];
     76     int mx=0,cnt=0;
     77     void update(int last,int &now,int l,int r,int x){
     78         sz[now=++cnt]=sz[last]+1,sum[now]=sum[last];
     79         if(l==r){sum[now]+=x;return;}
     80         int mid=(l+r)>>1;
     81         if(x<=mid) R[now]=R[last],update(L[last],L[now],l,mid,x);
     82         else L[now]=L[last],update(R[last],R[now],mid+1,r,x);
     83         sum[now]=sum[L[now]]+sum[R[now]];
     84     }
     85     int query(int u,int v,int l,int r,int k){
     86         if(sz[v]-sz[u]<=k) return sum[v]-sum[u];
     87         if(l==r) return (sum[v]-sum[u])/(sz[v]-sz[u])*k;
     88         int mid=(l+r)>>1;
     89         if(sz[R[v]]-sz[R[u]]>=k) return query(R[u],R[v],mid+1,r,k);
     90         else return query(L[u],L[v],l,mid,k-(sz[R[v]]-sz[R[u]]))+sum[R[v]]-sum[R[u]];
     91     }
     92     void main(){
     93         mx=1000;
     94         for(int i=1;i<=m;++i){
     95             int x=read();
     96             update(rt[i-1],rt[i],1,mx,x);
     97         }
     98         while(q--){
     99             int a=read(),b=read(),c=read(),d=read(),h=read();
    100             --b;
    101             int l=1,r=d-b+1;
    102             while(l<r){
    103                 int mid=(l+r)>>1;
    104                 if(query(rt[b],rt[d],1,mx,mid)>=h) r=mid;
    105                 else l=mid+1;
    106             }
    107             if(r==d-b+1) puts("Poor QLW");
    108             else printf("%d
    ",l);
    109         }
    110     }
    111 }
    112 int main(){
    113     //freopen("testdata.in","r",stdin);
    114     n=read(),m=read(),q=read();
    115     if(n!=1) solve1::main();
    116     else solve2::main();
    117     return 0;
    118 }
  • 相关阅读:
    算法笔记codeup-Contest100000568
    算法笔记codeup-Contest100000567
    算法笔记codeup-Contest100000566
    人工智能各种知识点(大杂烩)
    人工智能基础知识复习:机器学习
    人工智能基础知识复习:神经计算 演化计算 模糊计算
    人工智能基础知识复习:问题求解与搜索
    人工智能基础知识复习:推理技术
    前端基础知识学习:概念篇
    MYSQL
  • 原文地址:https://www.cnblogs.com/bztMinamoto/p/9387886.html
Copyright © 2011-2022 走看看