【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 ...
随机推荐
- IIS7,IIS7.5 URL重写模块工具
URL 重写模块 2.0 提供基于规则的重写机制,可在 Web 服务器处理请求的 URL 之前对其进行更改,以及在向 HTTP 客户端提供响应内容之前修改响应内容. 注意:使用环境为IIS7.0(x6 ...
- PAT 甲级 1012 The Best Rank
https://pintia.cn/problem-sets/994805342720868352/problems/994805502658068480 To evaluate the perfor ...
- do_try_to_free_pages
/* * This is the main entry point to direct page reclaim. * * If a full scan of the inactive list fa ...
- Kafka性能之道
Kafka高性能之道 高效使用磁盘 零拷贝 批处理和压缩 Partition ISR 高效使用磁盘 >顺序写cipan >Append Only(数据不更新,无记录级的数据删除,只会整个s ...
- 2019 front end jobs collection
2019 front end jobs collection Alibaba https://ant.design/docs/spec/work-with-us-cn https://www.yuqu ...
- Go语言【第四篇】:Go运算符
Go语言运算符 运算符用于在程序运行时执行数据或逻辑运算,Go语言内置的运算符有: 算数运算符 关系运算符 逻辑运算符 位运算符 赋值运算符 其他运算符 算数运算符 下表列出了所有Go语言的算数运算符 ...
- BZOJ4027 HEOI2015兔子与樱花(贪心)
首先显然地如果某个点超过了最大负载,删掉它仍然是不合法的.删除某个点当前只会对其父亲产生影响,同一个节点的儿子显然应该按代价从小到大删.考虑如果删掉某个点之后他的父亲不能再删了,我们损失了父亲这个点, ...
- 【题解】51nod 1686第K大区间
成功的秘诀,在于克服自己看题解的冲动……[笑哭].自己A掉这题还是灰常开心的~ 以及爱死 two - pointer ! two - pointer 大法是真的好哇……这个题目有上一题的经验:求第\( ...
- [LOJ#2340] [WC2018] 州区划分
题目链接 洛谷题面. LOJ题面.还是LOJ机子比较快 Solution 设\(f(s)\)表示选\(s\)这些城市的总代价,那么我们可以得到一个比较显然的\(dp\): \[ f(s)=\frac{ ...
- BZOJ1856:[SCOI2010]字符串——题解
https://www.lydsy.com/JudgeOnline/problem.php?id=1856 lxhgww最近接到了一个生成字符串的任务,任务需要他把n个1和m个0组成字符串,但是任务还 ...