zoukankan      html  css  js  c++  java
  • 【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
    ",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
    ",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
    ",ans);
            }
        }
        return 0;
    }
  • 相关阅读:
    div 内容自动换行
    发邮件
    asp gridview
    授权 注册
    asp grid 增加和删除行数据
    计算两个日期相差的天数
    sql 删除数据库表 外键
    装完Centos7提示Initial setup of CentOS Linux 7 (core)(转载)
    如何用javac 和java 编译运行整个Java工程 (转载)【转】在Linux下编译与执行Java程序
    centos7 安装拼音输入法(转载)
  • 原文地址:https://www.cnblogs.com/noblex/p/9175218.html
Copyright © 2011-2022 走看看