【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 ...
随机推荐
- lintcode-6-合并排序数组
合并排序数组 合并两个排序的整数数组A和B变成一个新的数组. 样例 给出A=[1,2,3,4],B=[2,4,5,6],返回 [1,2,2,3,4,4,5,6] 挑战 你能否优化你的算法,如果其中一个 ...
- 原生js操作Dom节点:CRUD
知识点,依然会遗忘.我在思考到底是什么原因.想到研究生考试准备的那段岁月,想到知识体系的建立,知识体系分为正向知识体系和逆向知识体系:正向知识体系可以理解为教科书目录,逆向知识体系可以理解考试真题. ...
- Bookmark Sentry – 检查重复、删除死链书签 Chrome扩展
Bookmark Sentry 的用处,就是 处理重复的收藏夹的死链 . 重复链收藏.具体,请百度. Bookmark Sentry 下载 : https://files.cnblogs.com/f ...
- 主流 Kubernetes 发行版梳理
2014 年,Kubernetes 作为内部 Google orchestrator Borg 开源版本推出,目前已是最成功和发展最快的 IT 基础架构项目之一.2018 年,Kubernetes 已 ...
- android eclipse 添加libs文件夹
导入一个项目发现没有libs文件夹,后来z自己新建了个lib文件夹,但是总是不行,后来发现错了,应该是libs文件夹.建完了之后,系统会自动在build path中把这个文件夹添加进来的:个人无须操作
- Visual Stdio 2015打包安装项目的方法(使用Visual Studio Installer)
首先在官网下载VS2015的Visual Studio Installer 1.创建安装项目 里面最左侧的框框有三个文件夹 1.“应用程序文件夹”即"Application Folder&q ...
- 【题解】HNOI2004敲砖块
题目传送门:洛谷1437 决定要养成随手记录做过的题目的好习惯呀- 这道题目乍看起来和数字三角形有一点像,但是仔细分析就会发现,因为选定一个数所需要的条件和另一个数所需要的条件会有重复的部分,所以状态 ...
- 【以前的空间】vijos 1720 阿狸的打字机
https://www.vijos.org/p/1720 作为一个一个蒟蒻,跪了三个星期,终于在蔡大神的帮助下a了.这题网上的题解很多,不过大都把题解写的太简单了(对因为大神的题解只有三个字:傻叉题) ...
- 以安装PyTorch为例说明Anaconda在Windows/Linux上的使用
在Windows10上配置完MXNet 1.3.0后,再配置PyTorch 1.0时,发现两者需要依赖的NumPy版本不一致,之前是通过pip安装NumPy,根据pip的版本不同,会安装不同版本的Nu ...
- POJ3415:Common Substrings——题解
http://poj.org/problem?id=3415 给定两个字符串A 和B,求长度不小于k 的公共子串的个数(可以相同). 论文题,和上道题(POJ2774)类似,首先想到现将AB串合并,然 ...