博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
[SDOI2010] 粟粟的书架
阅读量:4515 次
发布时间:2019-06-08

本文共 2784 字,大约阅读时间需要 9 分钟。

明显的二合一问题。贪心的想,要个数最少,那么久从页数多的开始选。于是对于前50%的数据,可以直接预处理(1~x,1~y)矩阵内大于等于k的元素个数、元素之和的前缀和,然后二分k值来验证;对于后50%的数据,已经退化为一维情形,若再使用前面的方法会mle(5e51e34),那么考虑使用主席树来维护:每个节点建一棵权值线段树,查询时区间内优先选择有区间即可。

可知两种方法的时间复杂度都是O(Qlog1000)

#include 
using namespace std;int n,m,q;namespace sofeerDure { const int N=207; int p[201][201]; int f[1001][201][201]; int g[1001][201][201]; #define sum (f[mid][c][d]-f[mid][a-1][d]-f[mid][c][b-1]+f[mid][a-1][b-1]) #define num (g[mid][c][d]-g[mid][a-1][d]-g[mid][c][b-1]+g[mid][a-1][b-1]) static void main() { for(int i=1; i<=n; ++i) { for(int j=1; j<=m; ++j) { scanf("%d",&p[i][j]); } } for(int k=1; k<=1000; ++k) { for(int i=1; i<=n; ++i) { for(int j=1; j<=m; ++j) { f[k][i][j]=f[k][i-1][j]+f[k][i][j-1]-f[k][i-1][j-1]; g[k][i][j]=g[k][i-1][j]+g[k][i][j-1]-g[k][i-1][j-1]; if(p[i][j]>=k) f[k][i][j]+=p[i][j], g[k][i][j]++; } } } for(int a,b,c,d,h; q--; ) { scanf("%d%d%d%d%d",&a,&b,&c,&d,&h); int l=1,r=1000,mid,ans=-1; while(l<=r) { mid=(l+r)>>1; if(sum>=h) ans=mid, l=mid+1; else r=mid-1; } if((mid=ans)<0) puts("Poor QLW"); else printf("%d\n",num-(sum-h)/mid); } } #undef sum #undef num} namespace haibaraDure { const int N=5e5+10; struct Node { int ls,rs,sum,num; } t[N*20]; int root[N],tot; int build(int l,int r) { int x=++tot; if(l==r) return x; int mid=(l+r)>>1; t[x].ls=build(l,mid); t[x].rs=build(mid+1,r); return x; } int insert(int x,int l,int r,int p) { int y=++tot; t[y]=t[x]; t[y].sum+=p; t[y].num++; if(l==r) return y; int mid=(l+r)>>1; if(p<=mid) t[y].ls=insert(t[x].ls,l,mid,p); else t[y].rs=insert(t[x].rs,mid+1,r,p); return y; } int query(int x,int y,int l,int r,int k) { if(l==r) return (k-1)/l+1; int mid=(l+r)>>1; int dif=t[t[y].rs].sum-t[t[x].rs].sum; if(k<=dif) return query(t[x].rs,t[y].rs,mid+1,r,k); else return query(t[x].ls,t[y].ls,l,mid,k-dif)+t[t[y].rs].num-t[t[x].rs].num; } static void main() { root[0]=build(1,1000); for(int i=1,x; i<=m; ++i) { scanf("%d",&x); root[i]=insert(root[i-1],1,1000,x); } for(int a,b,c,d,h; q--; ) { scanf("%d%d%d%d%d",&a,&b,&c,&d,&h); if(t[root[d]].sum-t[root[b-1]].sum
1) sofeerDure::main(); else haibaraDure::main(); return 0;}

转载于:https://www.cnblogs.com/nosta/p/10193675.html

你可能感兴趣的文章
void及void指针含义的深刻解析
查看>>
标准差(standard deviation)和标准误差(standard error)你能解释清楚吗?
查看>>
南阳oj 题目722 数独
查看>>
小米平板6.0以上系统如何不用Root激活Xposed框架的步骤
查看>>
Elliptical Arcs with SVG
查看>>
做好微博营销的技巧与步骤
查看>>
Docker从入门到实战(二)
查看>>
自定义相机
查看>>
Oracle 体系结构2 - 实例和数据库
查看>>
关于Unity中Vector2和Vector3的使用
查看>>
类与方法
查看>>
Python学习笔记(九) map、zip和filter函数
查看>>
吴裕雄 Bootstrap 前端框架开发——Bootstrap 字体图标(Glyphicons):glyphicon glyphicon-plus-sign...
查看>>
吴裕雄--天生自然 JAVASCRIPT开发学习:比较 和 逻辑运算符
查看>>
html 存放PDF文档
查看>>
setTimeout 传参
查看>>
PC客户端开发细节记录:保存GUID到VARIANT
查看>>
day5感想
查看>>
给DEDE织梦CMS添加搜索结果页显示自定义字段
查看>>
第二章 第五节 获取帮助
查看>>