BZOJ 1926: [Sdoi2010]粟粟的书架(主席树,二分答案)

  • 题意 :

给你一个长为\(R\)宽为\(C\)的矩阵,第\(i\)行\(j\)列的数为\(P_{i,j}\).

有\(m\)次询问,每次有5个参数\(x_l,x_r,y_l,y_r,h\). 求以\((x_l,y_l)\)为左上角和\((x_r,y_r)\)为右下角的矩形中,至少要选几个值,使得它们的和\(\geq h\).

  • 数据范围 :

对于\(50 \%\)的数据,满足\(R,C \le 200,M \le 200,000\)

另有\(50 \%\)的数据,满足\(R=1,C \le 500,000,M \le 20,000\)

对于\(100 \%\)的数据,满足\(1 \le P_{i,j} \le 1,000, 1 \le h \le 2,000,000,000\)

  • 题解 :

这道题很有意思2333

这个题相当于二合一吧,两种不同的方法解决它的子问题(但殊途同归).

  • 第一个\(R,C \le 200,M \le 200,000\).

    这个是有点类似于暴力的做法,首先预处理出每种数字出现次数的关于位置和数字大小前缀和,以及出现数字和关于位置数字大小的前缀和.

    这个有点绕,直接举例子吧.比如我程序中的Sum[i][j][k]Tot[i][j][k].

    Sum[i][j][k]就是以\((1,1)\)为左上角\((i,j)\)为右下角矩形的,数字\(\ge k\)的和.

    Tot[i][j][k]就是以\((1,1)\)为左上角\((i,j)\)为右下角矩形的,数字\(\ge k\)的出现次数的和.

    然后每次就可以二分你需要选的最小的数字了,每次判断可行就直接前缀和容斥就行了.

    然后这个选的最小数字不一定要选满,要最后算一下这个数字要选多少个.

    令\(n=max(P_{i,j})\)时间复杂度\(O(nRC+m \log n)\),空间复杂度\(O(nRC)\).

  • 第二个\(R=1,C \le 500,000,M \le 20,000\).

    这个就是一个序列操作了,这个我认为是这道题的精髓.

    我们沿用前一个算法的思想,也是要处理序列上那两个东西.

    但时间复杂度肯定要进行优化. 所以有一个数据结构可以支持这个操作,就是主席树!

    主席树不仅支持查找区间第\(k\)大,而且还能支持查找区间在\([l,r]\)中数字的和 和 出现数字的和!(看来我数据结构学的真的蠢啊) 以后出现这种题要往这上面想想了.

    然后我们可以每次算答案的时候直接在主席树上二分就行了和刚才的操作差不多吧,也类似于查找第\(k\)大.

    时间复杂度\(O(C \log n + m \log n)\),空间复杂度\(O(C \log n)\).

  • 代码 :

/**************************************************************
    Problem: 1926
    User: zjp_shadow
    Language: C++
    Result: Accepted
    Time:4688 ms
    Memory:509916 kb
****************************************************************/

#include <bits/stdc++.h>
#define For(i, l, r) for(register int i = (l), _end_ = (int)(r); i <= _end_; ++i)
#define Fordown(i, r, l) for(register int i = (r), _end_ = (int)(l); i >= _end_; --i)
#define Set(a, v) memset(a, v, sizeof(a))
using namespace std;

bool chkmin(int &a, int b) {return b < a ? a = b, 1 : 0;}
bool chkmax(int &a, int b) {return b > a ? a = b, 1 : 0;}

inline int read() {
    int x = 0, fh = 1; char ch = getchar();
    for (; !isdigit(ch); ch = getchar() ) if (ch == '-') fh = -1;
    for (; isdigit(ch); ch = getchar() ) x = (x<<1) + (x<<3) + (ch ^ '0');
    return x * fh;
}

void File() {
#ifdef zjp_shadow
    freopen ("P1926.in", "r", stdin);
    freopen ("P1926.out", "w", stdout);
#endif
}

const int N = 5e5 + 1e3;
const int maxnode = N * 20;

int take;

inline int Updiv(int a, int b) { return (a / b) + (a % b ? 1 : 0); }

struct ChairMan_Tree {
    int T[N], sumv[maxnode], tot[maxnode], lc[maxnode], rc[maxnode], Size;
    ChairMan_Tree () { Size = 0; }

    void Update(int &o, int pre, int l, int r, int up) {
        o = ++Size; lc[o] = lc[pre]; rc[o] = rc[pre];
        sumv[o] = sumv[pre] + up; tot[o] = tot[pre] + 1;
        if (l == r) return ;

        int mid = (l + r) >> 1;
        if (up <= mid) Update(lc[o], lc[pre], l, mid, up);
        else Update(rc[o], rc[pre], mid + 1, r, up);
    }

    void Query(int s, int t, int l, int r, int val) {
        if (l == r) { take += Updiv(val, l); return ; }
        int here = tot[rc[t]] - tot[rc[s]], sv = sumv[rc[t]] - sumv[rc[s]], mid = (l + r) >> 1;
        if (val > sv) { take += here; Query(lc[s], lc[t], l, mid, val - sv); }
        else Query(rc[s], rc[t], mid + 1, r, val);
    }
} CT;

int r, c, m;
int Mat[210][210];
int Sum[210][210][1010];
int Tot[210][210][1010];

int sum[N];

void Solve2() {
    For (i, 1, c) {
        int val = read();
        sum[i] = sum[i - 1] + val;
        CT.Update(CT.T[i], CT.T[i - 1], 1, 1000, val);
    }
    For (i, 1, m) {
        read(); int l = read(); read(); int r = read(), h = read();
    //  cout << "Ask: " << l << ' ' << r << ' ' << h << endl;
        take = 0;
        if (sum[r] - sum[l - 1] < h) { printf ("Poor QLW\n"); continue ; }
        CT.Query(CT.T[l - 1], CT.T[r], 1, 1000, h);
        printf ("%d\n", take);
    }
}

inline int Calc_Sum (int xl, int yl, int xr, int yr, int low) {
    return Sum[xr][yr][low] - Sum[xl - 1][yr][low] - Sum[xr][yl - 1][low] + Sum[xl - 1][yl - 1][low];
}

inline int Calc_Tot (int xl, int yl, int xr, int yr, int low) {
    return Tot[xr][yr][low] - Tot[xl - 1][yr][low] - Tot[xr][yl - 1][low] + Tot[xl - 1][yl - 1][low];
}

void Solve1() {
    For (i, 1, r)
        For (j, 1, c) {
            Mat[i][j] = read(); Sum[i][j][Mat[i][j]] += Mat[i][j]; ++Tot[i][j][Mat[i][j]];
            For (k, 1, 1000) {
                Sum[i][j][k] += Sum[i][j - 1][k] + Sum[i - 1][j][k] - Sum[i - 1][j - 1][k];
                Tot[i][j][k] += Tot[i][j - 1][k] + Tot[i - 1][j][k] - Tot[i - 1][j - 1][k];
            }
        }

    For (i, 1, r)
        For (j, 1, c)
            Fordown (k, 1000, 1) {
                Sum[i][j][k] += Sum[i][j][k + 1];
                Tot[i][j][k] += Tot[i][j][k + 1];
            }

    For (i, 1, m) {
        int xi = read(), yi = read(), xj = read(), yj = read(), h = read();
        int l = 1, r = 1000, need = -1;
        while (l <= r) {
            int mid = (l + r) >> 1;
            if (Calc_Sum(xi, yi, xj, yj, mid) >= h) need = mid, l = mid + 1;
            else r = mid - 1;
        }
        if (need == -1) { printf ("Poor QLW\n"); continue ; }
        int Btot = Calc_Tot(xi, yi, xj, yj, need + 1),
            Bsum = Calc_Sum(xi, yi, xj, yj, need + 1);
        Btot += Updiv(h - Bsum, need);
        printf ("%d\n", Btot);
    }
}

int main () {
    File();
    r = read(); c = read(); m = read();
    if (r == 1) Solve2(); else Solve1();
    return 0;
}

BZOJ 1926: [Sdoi2010]粟粟的书架(主席树,二分答案)的更多相关文章

  1. bzoj 1926: [Sdoi2010]粟粟的书架

    #include<cstdio> #include<iostream> #define N 201 #define M 500008 using namespace std; ...

  2. BZOJ 3514: Codechef MARCH14 GERALD07加强版 [LCT 主席树 kruskal]

    3514: Codechef MARCH14 GERALD07加强版 Time Limit: 60 Sec  Memory Limit: 256 MBSubmit: 1312  Solved: 501 ...

  3. 【BZOJ 3626】 [LNOI2014]LCA【在线+主席树+树剖】

    题目链接: TP 题解:   可能是我比较纱布,看不懂题解,只好自己想了…… 先附一个离线版本题解[Ivan] 我们考虑对于询问区间是可以差分的,然而这并没有什么卵用,然后考虑怎么统计答案. 首先LC ...

  4. 13年山东省赛 Boring Counting(离线树状数组or主席树+二分or划分树+二分)

    转载请注明出处: http://www.cnblogs.com/fraud/          ——by fraud 2224: Boring Counting Time Limit: 3 Sec   ...

  5. bzoj 2733: [HNOI2012]永无乡 离线+主席树

    2733: [HNOI2012]永无乡 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1167  Solved: 607[Submit][Status ...

  6. BZOJ 3514: Codechef MARCH14 GERALD07加强版( LCT + 主席树 )

    从左到右加边, 假如+的边e形成环, 那么记下这个环上最早加入的边_e, 当且仅当询问区间的左端点> _e加入的时间, e对答案有贡献(脑补一下). 然后一开始是N个连通块, 假如有x条边有贡献 ...

  7. 【BZOJ2653】【主席树+二分】middle

    Description 一个长度为n的序列a,设其排过序之后为b,其中位数定义为b[n/2],其中a,b从0开始标号,除法取下整. 给你一个长度为n的序列s. 回答Q个这样的询问:s的左端点在[a,b ...

  8. BZOJ 1734: [Usaco2005 feb]Aggressive cows 愤怒的牛( 二分答案 )

    最小最大...又是经典的二分答案做法.. -------------------------------------------------------------------------- #inc ...

  9. [BZOJ 2500]幸福的道路 树形dp+单调队列+二分答案

    考试的时候打了个树链剖分,而且还审错题了,以为是每天找所有点的最长路,原来是每天起点的树上最长路径再搞事情.. 先用dfs处理出来每个节点以他为根的子树的最长链和次长链.(后面会用到) 然后用类似dp ...

随机推荐

  1. os.path 大全

    os.path.abspath(path) #返回绝对路径 os.path.basename(path) #返回一个路径的最后一个组成部分 os.path.commonprefix(list) #返回 ...

  2. linux网络:常用命令(二)

    1.ping命令:与Windows下基本功能一样但也有所区别 1.命令格式: ping [选项] ip地址或域名主机等 选项 -c 加次数 -d 使用Socket的SO_DEBUG功能. -f 极限检 ...

  3. 《BI那点儿事—数据的艺术》理解维度数据仓库——事实表、维度表、聚合表

    事实表 在多维数据仓库中,保存度量值的详细值或事实的表称为“事实表”.一个按照州.产品和月份划分的销售量和销售额存储的事实表有5个列,概念上与下面的示例类似. Sate Product Mouth U ...

  4. Mac 系统下类似于 apt-get 的软件包管理器 -- Homebrew

    对于一个习惯了在 Ubuntu 的终端上通过 apt-get 来安装工具软件的我来说,也希望在Mac上找到类似的工具,能很方便的一条命令就能安装所需的软件,而不用手工的去查找下载编译,或者是折腾安装所 ...

  5. 【基础知识】.Net基础加强09天

    委托: 1. 委托是一种数据类型,像类一样{可以声明委托变量类型} 2. deleate关键字定义委托 : public delegate void MethodDelegate();//这就是定义了 ...

  6. [jQuery学习系列六]6-jQuery实际操作小案例

    前言最后在这里po上jQuery的几个小案例. Jquery例子1_占位符使用需求: 点击第一个按钮后 自动去check 后面是否有按钮没有选中, 如有则提示错误消息. <html> &l ...

  7. MBR中“起始磁头/扇区/柱面“同&quot;逻辑区块地址(LBA)&quot;的区别

    "起始磁头/扇区/柱面"共有3个字节,最大能表示8G的扇区编号.当硬盘扇区编号多于8G时,此表示法便力不从心,便使用4个字节的LBA表示法(逻辑扇区地址,相对扇区地址). 算是计算 ...

  8. 转:Jmeter之Bean shell使用(一)

    一.什么是Bean Shell BeanShell是一种完全符合Java语法规范的脚本语言,并且又拥有自己的一些语法和方法; BeanShell是一种松散类型的脚本语言(这点和JS类似); BeanS ...

  9. vega prime 1.2 (视景仿真)

    Vega Prime 1.2 (视景仿真) MPI的视景仿真渲染工具Vega是世界上领先的应用于实时视景仿真.声音仿真和虚拟现实等领域的软件环境,它用来渲染战场仿真.娱乐.城市仿真.训练模拟器和计算可 ...

  10. 使用配置方式进行ssh的整合以及管理员管理的案例(二)

    (续) 删除Hibernate配置文件的写法: 在applicationContext.xml中添加数据库操作的相关配置: <!-- 配置数据库连接池 -->    <bean id ...