题目大意:

网址:https://daniu.luogu.org/problemnew/show/2468
大意:本题有两问:
[1] 给定一个\(R*C\)的带权矩阵,询问\(2×10^5\)次在一个子矩阵内至少选择多少个点使他们的权值和大于\(H\)。
[2] 给定长度为L的一条链,询问\(2×10^4\)次在一个区间\([L,R]\)中至少选择多少个点使他们的权值和大于\(H\)。
数据范围:对于两问,都有权值\(P<=1000\),第一问中\(R、C<=200\),第二问中\(L<=5\times 10^5\)。

题目解法

第一问(Solve1):

观察到\(R×C×P\)无论是在时间还是在空间上都是可以接受的。
直接开两个前缀和:
\(data[d][i][j]\)为值到了d时的权值和,\(sum[d][i][j]\)为值到了d时的人数和。
那么每次二分一个权值d,然后二维前缀和查询Check即可。

第二问(Solve2):

正解是主席树,然而我自己 yy 出了一个 .... 总统树 ?
还是线段树为基础,进行可持久化,从大往小对于每一个权值建立一棵树。
直接建1000棵线段树肯定是不现实的。所以考虑用主席树的那种搞法。
对于更新路径上的节点。如果还没有新建节点,就建立一个新结点。
那么向下走的时候,走的那个方向如果还没有建立新结点,则要新建,否则走本轮建的结点。
不走的那个方向直接用前一历史版本的即可。

if(ps<=mid){
        if(!rs[ro])rs[ro] = rs[lst];        //沿用上一版本
        if(ls[ro] == ls[lst])ls[ro] = 0;    //更新的路径上所有节点必须新建。
        Update2(ls[ro],l,mid,ps,dt,ls[lst]);
}

上面这个代码中lst是上一个历史版本,ro为本轮版本。
与这题类似的还有[SDOI2014]旅行,都是要自己 yy 可持久化或动态的数据结构。
完成建树后,一样的对与每一个询问二分一个权值d,然后Check即可。

具体实现代码:

#include<bits/stdc++.h>
#define maxn 10000000
#define gi(x) scanf("%d",&x);
using namespace std;

int oo,R,C,M,H,x11,x22,y11,y22;
int data[1005][205][205],sum[1005][205][205];
int ls[maxn],rs[maxn],rt[1005],val[maxn],cnt[maxn];
vector<int>g[1005];

int Calc(int hg,int od){
    if(od == 0)return data[hg][x22][y22] + data[hg][x11-1][y11-1]
                    - data[hg][x22][y11-1] - data[hg][x11-1][y22];
    if(od == 1)return sum[hg][x22][y22] + sum[hg][x11-1][y11-1]
                    - sum[hg][x22][y11-1] - sum[hg][x11-1][y22];
}

int GetAns1(){
    if(Calc(1,0) < H)return -1;
    int L = 1,R = 1000,Res=-1,Ans=0,Last = 0;
    while(L<=R){
        int mid = (L+R)>>1;
        if(Calc(mid,0) >= H){Res = mid; L =mid+1;}
        else R = mid-1;
    }
    Ans = Calc(Res+1,1),Last = Calc(Res+1,0);
    return Ans + (H-Last+(Res-1))/Res;
}

void Solve1(){
    for(int i = 1,d; i <= R; i ++)
        for(int j = 1; j <= C; j ++){
            gi(d);
            data[d][i][j] = d;
            sum[d][i][j] = 1;
        }
    for(int d = 1; d <= 1000; d ++)
        for(int i = 1; i <= R; i ++)
            for(int j = 1; j <= C; j ++)
                data[d][i][j] += data[d][i][j-1] + data[d][i-1][j] - data[d][i-1][j-1],
                    sum[d][i][j] += sum[d][i][j-1] + sum[d][i-1][j] - sum[d][i-1][j-1];
    for(int d = 999; d >= 1; d --)
        for(int i = 1; i <= R; i ++)
            for(int j = 1; j <= C; j ++)
                data[d][i][j] += data[d+1][i][j], sum[d][i][j] += sum[d+1][i][j];
    for(int sq = 1,f; sq <= M; sq ++){
        gi(x11); gi(y11); gi(x22); gi(y22); gi(H);
        f = GetAns1();
        if(f == -1)printf("Poor QLW\n");
        else printf("%d\n",f);
    }
    return;
}

void Build2(int &ro,int l,int r){
    ro = ++oo;
    if(l == r)return;
    int mid = (l+r)>>1;
    Build2(ls[ro],l,mid); Build2(rs[ro],mid+1,r);
}

void PushUp2(int ro){
    val[ro] = val[ls[ro]] + val[rs[ro]];
    cnt[ro] = cnt[ls[ro]] + cnt[rs[ro]];
}

int Ret2(int ro,int typ){return (!typ) ? val[ro] : cnt[ro];}
int Query2(int ro,int l,int r,int tl,int tr,int typ){
    if(!ro || r<tl || l>tr)return 0;
    if(tl<=l && r<=tr)return Ret2(ro,typ);
    int mid = (l+r)>>1;
    return Query2(ls[ro],l,mid,tl,tr,typ)+Query2(rs[ro],mid+1,r,tl,tr,typ);
}

void Update2(int &ro,int l,int r,int ps,int dt,int lst){
    if(!ro){
        ro = ++oo;
        val[ro] = val[lst]; cnt[ro] = cnt[lst];
    }
    if(l == r){cnt[ro]+=1; val[ro]+=dt; return;}
    int mid = (l+r)>>1;
    if(ps<=mid){
        if(!rs[ro])rs[ro] = rs[lst];
        if(ls[ro] == ls[lst])ls[ro] = 0;
        Update2(ls[ro],l,mid,ps,dt,ls[lst]);
    }
    else if(ps>mid){
        if(!ls[ro])ls[ro] = ls[lst];
        if(rs[ro] == rs[lst])rs[ro] = 0;
        Update2(rs[ro],mid+1,r,ps,dt,rs[lst]);
    }
    PushUp2(ro);
}

void Solve2(){
    for(int i = 1,d; i <= C; i ++)
        {gi(d); g[d].push_back(i);}
    Build2(rt[1001],1,C);
    for(int i = 1000; i >= 1; i --){
        if(g[i].empty())rt[i] = rt[i+1];
        for(int j = 0; j < g[i].size(); j ++)
            Update2(rt[i],1,C,g[i][j],i,rt[i+1]);
    }
    for(int sq = 1; sq <= M; sq ++){
        gi(x11); gi(y11); gi(x22); gi(y22); gi(H);
        if(Query2(rt[1],1,C,y11,y22,0) < H){printf("Poor QLW\n");continue;}
        int L = 1,R = 1000,Res = -1,Ans,Last;
        while(L<=R){
            int mid = (L+R)>>1;
            if(Query2(rt[mid],1,C,y11,y22,0) >= H){Res = mid; L = mid+1;}
            else R = mid - 1;
        }
        Ans = Query2(rt[Res+1],1,C,y11,y22,1),Last = Query2(rt[Res+1],1,C,y11,y22,0);
        printf("%d\n",Ans + (H-Last+(Res-1))/Res);
    }
    return;
}

int main(){
    gi(R); gi(C); gi(M);
    if(R!=1)Solve1();
    if(R == 1)Solve2();
    return 0;
}

[SDOI2010]粟粟的书架的更多相关文章

  1. bzoj1926[Sdoi2010]粟粟的书架 二分 主席树

    1926: [Sdoi2010]粟粟的书架 Time Limit: 30 Sec  Memory Limit: 552 MBSubmit: 1064  Solved: 421[Submit][Stat ...

  2. bzoj 1926: [Sdoi2010]粟粟的书架 (主席树+二分)

    链接:https://www.lydsy.com/JudgeOnline/problem.php?id=1926 题面; 1926: [Sdoi2010]粟粟的书架 Time Limit: 30 Se ...

  3. [bzoj1926][Sdoi2010]粟粟的书架_二分_主席树

    粟粟的书架 bzoj-1926 Sdoi-2010 题目大意:题目链接 注释:略 想法:分成两个题 前面的我们可以二分,直接二分出来检验即可. 对于R=1的,相当一个数列,我们在上面建立主席树. 然后 ...

  4. Bzoj 1926: [Sdoi2010]粟粟的书架(二分答案+乱搞+主席树)

    1926: [Sdoi2010]粟粟的书架 Time Limit: 30 Sec Memory Limit: 552 MB Description 幸福幼儿园 B29 班的粟粟是一个聪明机灵.乖巧可爱 ...

  5. [SDOI2010]粟粟的书架 [主席树]

    [SDOI2010]粟粟的书架 考虑暴力怎么做 显然是提取出来 (x2-x1+1)*(y2-y1+1) 个数字拿出来 然后从大到小排序 然后就可以按次取数了- 然而接下来看数据范围 \(50\%\ r ...

  6. [BZOJ1926][SDOI2010]粟粟的书架

    BZOJ Luogu Description 幸福幼儿园 B29 班的粟粟是一个聪明机灵.乖巧可爱的小朋友,她的爱好是画画和读书,尤其喜欢 Thomas H. Cormen 的文章.粟粟家中有一个 R ...

  7. BZOJ1926[Sdoi2010]粟粟的书架——二分答案+主席树

    题目描述 幸福幼儿园 B29 班的粟粟是一个聪明机灵.乖巧可爱的小朋友,她的爱好是画画和读书,尤其喜欢 Thomas H. Co rmen 的文章.粟粟家中有一个 R行C 列的巨型书架,书架的每一个位 ...

  8. 【刷题】BZOJ 1926 [Sdoi2010]粟粟的书架

    Description 幸福幼儿园 B29 班的粟粟是一个聪明机灵.乖巧可爱的小朋友,她的爱好是画画和读书,尤其喜欢 Thomas H. Cormen 的文章.粟粟家中有一个 R行C 列的巨型书架,书 ...

  9. BZOJ1926:[SDOI2010]粟粟的书架——题解

    http://www.lydsy.com/JudgeOnline/problem.php?id=1926 https://www.luogu.org/problemnew/show/P2468 幸福幼 ...

  10. 【BZOJ1926】【SDOI2010】粟粟的书架 [主席树]

    粟粟的书架 Time Limit: 30 Sec  Memory Limit: 552 MB[Submit][Status][Discuss] Description 幸福幼儿园 B29 班的粟粟是一 ...

随机推荐

  1. Cookie禁用 获取session

    转自:http://blog.csdn.net/u010433704/article/details/40950599 Cookie与 Session,一般认为是两个独立的东西,Session采用的是 ...

  2. golang GET 出现 x509: certificate signed by unknown authority

    我们编写一个Go程序来尝试与这个HTTPS server建立连接并通信. //gohttps/4-https/client1.gopackage main import (    "fmt& ...

  3. redis —主从&&集群(CLUSTER)

    REDIS主从配置 为了节省资源,本实验在一台机器进行.即,在一台机器上启动两个端口,模拟两台机器. 机器准备: [root@adailinux ~]# cp /etc/redis.conf /etc ...

  4. centos 手动增加swap分区

    SWAP是Linux中的虚拟内存,用于扩充物理内存不足而用来存储临时数据存在的.它类似于Windows中的虚拟内存.在Windows中,只可以使用文件来当作虚拟内存.而linux可以文件或者分区来当作 ...

  5. JavaScript对象创建的几种方式

    1 工厂模式 1.1 创建 function createFruit(name,colors) { var o = new Object(); o.name = name; o.colors = co ...

  6. 使用C#开发C/S框架高级版添加新项目实例

    操作步骤: 1.新建一个项目CSFramework3.test,在CSFramework3.test项目下新建一个FormMan窗口(此时不需要继承). 2.按F7打开类,替换一下引用 using S ...

  7. DOCKER 无法获取使用宿主机DNS 的原因,解决方法

    今天在公司服务器上部署项目,遇到一个大坑.接口怎么请求都不同,宿主机DNS已经改了.宿主可以请求,找了半天,原来是DOCKER 没有获取到主机的DNS 进去DOCKER解析不了域名 指定DNS 启动也 ...

  8. 用pycharm+flask 建立项目以后运行出现ImportError: No module named flask-login问题

    出现此问题,一般情况下: 打开CMD输入: pip install flask-login 然后,在cmd中输入命令: pip list 查看目前已安装的的模板.在此时,如果你继续运行项目,有可能会发 ...

  9. Nginx反向代理实现Tomcat负载均衡

    这篇短文主要介绍Tomcat的集群和用Nginx反向代理实现Tomcat负载均衡. 1.首先需要对一些知识点进行扫盲(对自己进行扫盲,囧): 集群(Cluster) 简单来说就是用N台服务器构成一个松 ...

  10. 阿里云服务器部署笔记一(python3、Flask、uWSGI、Nginx)

    一.重置密码,并重启服务器 二.安全组配置>配置规则>添加安全组规则(为了能在本地ssh到实例) 配置如下: 此配置为允许任意公网IP登陆实例,注意windows与Linux系统端口范围不 ...