【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 ...
随机推荐
- SERVER 2008 R2 SP1下的内存虚拟盘(支持32位,64位的所有windows版本)
一时冲动把笔记本的系统换成了2008 R2 SP1的,本来想着用笔记本开HYPER-V的,结果是失败了,我发现我的4750G开了HYPER-V后CPU一直居高不下,其中有个什么系统软件保护的服务就占用 ...
- ManagementClass("Win32_Share")之共享目录
public class ShareFolder { private static readonly Dictionary<uint, string> ReturnDetails = ne ...
- 普通用户如何启动WCF服务
做Winform项目时,部署到客户机上有两个应用程序,Host和Client,在Host上运行着WCF服务供Client调用.平时现在在测试的时候都没发现有问题,但是当安装到客户的正式环境时发现服务启 ...
- Flink中的数据传输与背压
一图道尽心酸: 大的原理,上游的task产生数据后,会写在本地的缓存中,然后通知JM自己的数据已经好了,JM通知下游的Task去拉取数据,下游的Task然后去上游的Task拉取数据,形成链条. 但是在 ...
- solr 学习之数据导入
将数据库中的数据导入到我们的solr索引库中(DataImportHandler) 1.将jdbc的jar包和solr包中的DataImport的jar包拷贝到webapp中solr/WEB-INF/ ...
- Spring MVC之@RequestBody@ResponseBody详解
引言: 接上一篇文章讲述处理@RequestMapping的方法参数绑定之后,详细介绍下@RequestBody.@ResponseBody的具体用法和使用时机: 简介: @RequestBody 作 ...
- Spline样条函数 //C++关键字:operator // 重载函数 // 隐含的this指针 // 指针和const限定符
在数学学科数值分析中,样条是一种特殊的函数,由多项式分段定义.样条插值是使用一种名为样条的特殊分段多项式进行插值的形式.由于样条插值可以使用低阶多项式样条实现较小的差值误差,这样就避免了使用高阶多项式 ...
- (转)java +libsvm 安装与测试:
libsvm 用SVM实现简单线性分类 (转自:http://www.cnblogs.com/freedomshe/archive/2012/10/09/2717356.html) 0. 下载lib ...
- Oracle 转义字符
id sfds_V_SF ASD_V_DSAF SD_V_DSAD 下划线是Oracle特殊字符,需要转移,如下 select * from systab t where t.id like ...
- 【以前的空间】BZOJ2733[HNOI2012]永无乡
启发式合并?! 似乎当时写并查集的时候就有看到过类似于把小并查集并到大并查集上的说法,原来这就是启发式…… 具体做法就是把小树里面的一个个拿出来,然后加到大树里面去(裸的不敢相信) const max ...