【BZOJ1926】【SDOI2010】粟粟的书架 [主席树]
粟粟的书架
Time Limit: 30 Sec Memory Limit: 552 MB
[Submit][Status][Discuss]
Description
Input
Output
Sample Input
14 15 9 26 53
58 9 7 9 32
38 46 26 43 38
32 7 9 50 28
8 41 9 7 17
1 2 5 3 139
3 1 5 5 399
3 3 4 5 91
4 1 4 1 33
1 3 5 4 185
3 3 4 3 23
3 1 3 3 108
Sample Output
15
2
Poor QLW
9
1
3
HINT
Main idea
求给定矩阵(第二问是序列)中至少要取几个数加起来可以大于给定的值。
Solution
分为两部分实现:
第一部分n,m<=200,发现值<=1000,可以令tal表示到i,j位置为止的矩阵数值>=k的权值和与个数。每次二分最小值,判断是否可行,最后注意最小值不一定要取满。
第二部分为序列,用主席树求一段区间内>=某个值的权值和与个数,然后在主席树上二分,类似静态查询Kth,如果往左子树走则加上右子树的权值与个数,最后走到叶子节点的时候判断是否需要取满即可。
Code
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
using namespace std; const int ONE=;
const int TWO=;
const int INF=; int n,m,T;
int x,Need,cnt;
int res_num,res_value;
int a[ONE][ONE];
int X1,X2,Y1,Y2; struct power
{
int root;
int left,right;
int value,num;
}Node[TWO]; struct point
{
int num;
int value;
}tal[ONE][ONE][INF]; int get()
{
int res,Q=; char c;
while( (c=getchar())< || c>)
if(c=='-')Q=-;
if(Q) res=c-;
while((c=getchar())>= && c<=)
res=res*+c-;
return res*Q;
} void Update(int &x,int y,int l,int r,int Val)
{
x=++cnt;
Node[x].value=Node[y].value+Val;
Node[x].num=Node[y].num+;
Node[x].left=Node[y].left;
Node[x].right=Node[y].right;
if(l==r) return;
int mid=(l+r)/;
if(Val<=mid) Update(Node[x].left,Node[y].left,l,mid,Val);
if(mid+<=Val) Update(Node[x].right,Node[y].right,mid+,r,Val);
} void Query(int x,int y,int l,int r,int Need)
{
if(l==r)
{
if(Need && l)
{
int num=Need/l;
res_num+=num;
Need-=num*l;
if(Need>) res_num++,Need-=l;
}
res_value=Need;
return;
} int mid=(l+r)/;
int value=Node[ Node[y].right ].value-Node[ Node[x].right ].value;
if(value > Need)
Query(Node[x].right,Node[y].right,mid+,r,Need);
else
{
res_num+=Node[ Node[y].right ].num-Node[ Node[x].right ].num;
Query(Node[x].left,Node[y].left,l,mid,Need-value);
}
} int Getvalue(int Val)
{
return tal[X2][Y2][Val].value + tal[X1-][Y1-][Val].value - tal[X1-][Y2][Val].value - tal[X2][Y1-][Val].value;
} int Getnum(int Val)
{
return tal[X2][Y2][Val].num + tal[X1-][Y1-][Val].num - tal[X1-][Y2][Val].num - tal[X2][Y1-][Val].num;
} void Deal(int ans)
{
res_num=Getnum(ans+);
res_value=Getvalue(ans+);
Need-=res_value;
if(Need>=)
{
int num=Need/ans;
res_num+=num;
Need-=num*ans;
if(Need>) res_num++,Need-=ans;
}
} void PartOne()
{
for(int i=;i<=n;i++)
for(int j=;j<=m;j++)
{
a[i][j]=get();
} for(int k=;k<=;k++)
{
for(int i=;i<=n;i++)
{
for(int j=;j<=m;j++)
{
tal[i][j][k].value=tal[i][j-][k].value;
tal[i][j][k].num=tal[i][j-][k].num;
if(a[i][j]>=k) tal[i][j][k].value+=a[i][j],tal[i][j][k].num++;
} for(int j=;j<=m;j++)
{
tal[i][j][k].value+=tal[i-][j][k].value;
tal[i][j][k].num+=tal[i-][j][k].num;
}
}
} while(T--)
{
Need=;
X1=get(); Y1=get(); X2=get(); Y2=get(); Need=get();
if(Getvalue()<Need)
{
printf("Poor QLW\n");
continue;
}
int l=,r=; int ans=;
while(l<=r)
{
int mid=(l+r)/;
if(Getvalue(mid)>Need)
{
ans=mid;
l=mid+;
}
else r=mid-;
} if(!ans) ans=;
res_num=res_value=;
Deal(ans);
printf("%d\n",res_num);
}
} void PartTwo()
{
for(int i=;i<=m;i++)
{
x=get();
Update(Node[i].root,Node[i-].root,,INF,x);
} int x1,x2,y1,y2;
while(T--)
{
x1=get(); y1=get(); x2=get(); y2=get(); Need=get();
int l=,r=; res_num=res_value=;
Query(Node[y1-].root,Node[y2].root,,INF,Need);
if(res_value>) printf("Poor QLW\n");
else
printf("%d\n",res_num);
}
} int main()
{
n=get(); m=get(); T=get();
if(n!=) PartOne();
else PartTwo();
}
【BZOJ1926】【SDOI2010】粟粟的书架 [主席树]的更多相关文章
- bzoj 1926: [Sdoi2010]粟粟的书架 (主席树+二分)
链接:https://www.lydsy.com/JudgeOnline/problem.php?id=1926 题面; 1926: [Sdoi2010]粟粟的书架 Time Limit: 30 Se ...
- [SDOI2010]粟粟的书架 [主席树]
[SDOI2010]粟粟的书架 考虑暴力怎么做 显然是提取出来 (x2-x1+1)*(y2-y1+1) 个数字拿出来 然后从大到小排序 然后就可以按次取数了- 然而接下来看数据范围 \(50\%\ r ...
- BZOJ 1926: [Sdoi2010]粟粟的书架(主席树,二分答案)
BZOJ 1926: [Sdoi2010]粟粟的书架(主席树,二分答案) 题意 : 给你一个长为\(R\)宽为\(C\)的矩阵,第\(i\)行\(j\)列的数为\(P_{i,j}\). 有\(m\)次 ...
- [bzoj1926][Sdoi2010]粟粟的书架_二分_主席树
粟粟的书架 bzoj-1926 Sdoi-2010 题目大意:题目链接 注释:略 想法:分成两个题 前面的我们可以二分,直接二分出来检验即可. 对于R=1的,相当一个数列,我们在上面建立主席树. 然后 ...
- bzoj1926[Sdoi2010]粟粟的书架 二分 主席树
1926: [Sdoi2010]粟粟的书架 Time Limit: 30 Sec Memory Limit: 552 MBSubmit: 1064 Solved: 421[Submit][Stat ...
- BZOJ1926[Sdoi2010]粟粟的书架——二分答案+主席树
题目描述 幸福幼儿园 B29 班的粟粟是一个聪明机灵.乖巧可爱的小朋友,她的爱好是画画和读书,尤其喜欢 Thomas H. Co rmen 的文章.粟粟家中有一个 R行C 列的巨型书架,书架的每一个位 ...
- BZOJ1926 [Sdoi2010]粟粟的书架 【主席树 + 二分 + 前缀和】
题目 幸福幼儿园 B29 班的粟粟是一个聪明机灵.乖巧可爱的小朋友,她的爱好是画画和读书,尤其喜欢 Thomas H. Co rmen 的文章.粟粟家中有一个 R行C 列的巨型书架,书架的每一个位置都 ...
- 【BZOJ-1926】粟粟的书架 二分 + 前缀和 + 主席树
1926: [Sdoi2010]粟粟的书架 Time Limit: 30 Sec Memory Limit: 552 MBSubmit: 616 Solved: 238[Submit][Statu ...
- 【BZOJ1926】粟粟的书架(主席树,前缀和)
[BZOJ1926]粟粟的书架(主席树,前缀和) 题面 Description 幸福幼儿园 B29 班的粟粟是一个聪明机灵.乖巧可爱的小朋友,她的爱好是画画和读书,尤其喜欢 Thomas H. Co ...
随机推荐
- 关闭win7/Server 2008非正常关机启动自动修复功能
命令提示符下输入 bcdedit /set {default} bootstatuspolicy ignoreallfailures bcdedit /set {current} recoveryen ...
- C# 7.0 新特性
先列一下相关的语法: 1.out-variables(Out变量) 2.Tuples(元组) 3.Pattern Matching(匹配模式) 4.ref locals and returns (局部 ...
- 基本数据类型(int,bool,str)
目录: 1.int 数字类型 2.bool 布尔值 3.str 字符串类型 一.整型(int) 在python3中所有的整数都是int类型.但在python2中如果数据量 ...
- 整理下本周工作中遇到的疑问;uid/euid/suid;docker镜像管理
1.系统中的父子进程关系,以及docker是如何处理的这种父子进程关系,线上问题发现,子进程长时间得不到退出. 2.调用system系统调用发生了啥事情,发现大量的页表拷贝. 3.通过shell命令通 ...
- 【python】使用枚举类
当我们需要定义常量时,一个办法是用大写变量通过整数来定义,例如月份: JAN = 1 FEB = 2 MAR = 3 ... NOV = 11 DEC = 12 好处是简单,缺点是类型是int,并且仍 ...
- 2018 杭电多校1 - Distinct Values
题目链接 Problem Description Chiaki has an array of n positive integers. You are told some facts about t ...
- HTML、 CSS、 JavaScript三者的关系 1
HTML. CSS. JavaScript三者的关系 网页主要由三部分组成: 结构( Structure) . 表现( Presentation) 和行为( Behavior) HTML —— ...
- (转)linux sort,uniq,cut,wc命令详解
linux sort,uniq,cut,wc命令详解 sort sort 命令对 File 参数指定的文件中的行排序,并将结果写到标准输出.如果 File 参数指定多个文件,那么 sort 命令将这些 ...
- CentOS 文本操作命令
1.cat 用于查看纯文本文件,显示行号,加-n参数,适合内容较少的情况 2.more 用于查看纯文本文件,适合内容较多的情况 3.less 用于查看纯文本文件,可以上下翻页 4.head 用于查看纯 ...
- BZOJ1016:[JSOI2008]最小生成树计数——题解
https://www.lydsy.com/JudgeOnline/problem.php?id=1016 现在给出了一个简单无向加权图.你不满足于求出这个图的最小生成树,而希望知道这个图中有多少个不 ...