#二分,主席树#洛谷 2468 粟粟的书架

2024-02-11 05:18

本文主要是介绍#二分,主席树#洛谷 2468 粟粟的书架,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

题目

给出一个矩阵,问一个子矩阵中至少要多少个数才能使和 ≥ h \geq h h,多组数据,分成 1 ≤ r , c ≤ 200 和 r = 1 , 1 ≤ c ≤ 500000 1\leq r,c\leq 200和r=1,1\leq c\leq 500000 1r,c200r=1,1c500000


分析

这显然是一道以二分为核心的题目,但是这道题目二合一,对于 r ≠ 1 r\neq 1 r=1维护二维前缀大于等于某个值的数量以及它们的和,最后答案因为会有很多个相同的结果,所以要减掉,对于 r = 1 r=1 r=1用主席树同样维护,其实也和 r ≠ 1 r\neq 1 r=1的答案求法有同样的道理


代码

#include <cstdio>
#include <cctype>
#define rr register
using namespace std;
const int N=500011;
struct rec{int ws,wr,ls,rs;}b[N<<4];
int root[N],sw[201][201][1001],mx,sr[201][201][1001],tot,a[201][201],c[N],n,m,Q;
inline signed iut(){rr int ans=0; rr char c=getchar();while (!isdigit(c)) c=getchar();while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();return ans;
}
inline void print(int ans){if (ans>9) print(ans/10);putchar(ans%10+48);
}
inline signed max(int a,int b){return a>b?a:b;}
inline signed get_sw(int x1,int y1,int x2,int y2,int now){return sw[x2][y2][now]-sw[x1-1][y2][now]-sw[x2][y1-1][now]+sw[x1-1][y1-1][now];}
inline signed get_sr(int x1,int y1,int x2,int y2,int now){return sr[x2][y2][now]-sr[x1-1][y2][now]-sr[x2][y1-1][now]+sr[x1-1][y1-1][now];}
inline void update(int &rt,int l,int r,int x){b[++tot]=b[rt],rt=tot,b[rt].ws+=x,++b[rt].wr;if (l==r) return; rr int mid=(l+r)>>1;if (x<=mid) update(b[rt].ls,l,mid,x);else update(b[rt].rs,mid+1,r,x);
}
inline signed query(int rt1,int rt2,int l,int r,int h){rr int ans=0;while (l<r){rr int mid=(l+r)>>1,now=b[b[rt2].rs].ws-b[b[rt1].rs].ws;if (now<=h) ans+=b[b[rt2].rs].wr-b[b[rt1].rs].wr,h-=now,r=mid,rt2=b[rt2].ls,rt1=b[rt1].ls;else l=mid+1,rt1=b[rt1].rs,rt2=b[rt2].rs;}ans+=(h+l-1)/l;return ans;
}
signed main(){n=iut(),m=iut(),Q=iut();if (n^1){for (rr int i=1;i<=n;++i)for (rr int j=1;j<=m;++j) mx=max(mx,a[i][j]=iut());for (rr int k=0;k<=mx;++k)for (rr int i=1;i<=n;++i)for (rr int j=1;j<=m;++j)sw[i][j][k]=sw[i-1][j][k]+sw[i][j-1][k]-sw[i-1][j-1][k]+(a[i][j]>=k?a[i][j]:0),sr[i][j][k]=sr[i-1][j][k]+sr[i][j-1][k]-sr[i-1][j-1][k]+(a[i][j]>=k);while (Q--){rr int x1=iut(),y1=iut(),x2=iut(),y2=iut(),h=iut();if (get_sw(x1,y1,x2,y2,0)<h) printf("Poor QLW");else{rr int l=0,r=mx;while (l<r){rr int mid=(l+r+1)>>1;if (get_sw(x1,y1,x2,y2,mid)>=h) l=mid;else r=mid-1;}print(get_sr(x1,y1,x2,y2,l)-(get_sw(x1,y1,x2,y2,l)-h)/l);}putchar(10);}}else{for (rr int i=1;i<=m;++i) mx=max(mx,c[i]=iut());for (rr int i=1;i<=m;++i) update(root[i]=root[i-1],1,mx,c[i]);while (Q--){rr int x1=iut(),y1=iut(),x2=iut(),y2=iut(),h=iut();if (b[root[y2]].ws-b[root[y1-1]].ws<h) printf("Poor QLW");else print(query(root[y1-1],root[y2],1,mx,h));putchar(10);}}return 0;
}

这篇关于#二分,主席树#洛谷 2468 粟粟的书架的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/698923

相关文章

二分查找(算法篇)

算法之二分查找 二分查找 概念: 针对于已经预先排序好的数据,每次将数据进行对半查找,然后看它中间的数据是否是要找的,如果是就返回中间位置,不是就判断该数据是在前半部分还是后半部,然后在进而取其中部,看其是否找到,然后如果还没找到就一直重复操作,直到找到为止,该算法时间复杂度为O(logn) 代码: int search(vector<int>& nums, int target) {i

C语言实现简单二分搜索和四个变体问题

二分查找 简单的二分查找 简单指的是在不存在重复元素的数组中,查找值等于给定值的情况。 int bsearch(int *arr, int n, int value){int low = 0;int high = n - 1;int mid;while (low <= high){mid = low + ((high-low) >> 1);if (arr[mid] == value){re

洛谷 P10584 [蓝桥杯 2024 国 A] 数学题(整除分块+杜教筛)

题目 思路来源 登录 - Luogu Spilopelia 题解 参考了两篇洛谷题解,第一篇能得出这个式子,第二篇有比较严格的复杂度分析 结合去年蓝桥杯洛谷P9238,基本就能得出这题的正确做法 代码 #include<bits/stdc++.h>#include<iostream>#include<cstdio>#include<map>#include<uno

leetcode 二分查找·系统掌握 x的平方根

题目: 题解 这题可以使用~01~泛型查找在0~x/2的范围内查找答案。 int mySqrt(int x) {long l=0,r=x,mid;while(l<r){mid=(l+r+1)>>1;if(mid*mid>x)r=mid-1;else l=mid;}//因为一定有答案所以不用判定是否查找失败return l;}

洛谷P8502题解

[problem] \color{blue}{\texttt{[problem]}} [problem] [Solution] \color{blue}{\texttt{[Solution]}} [Solution] 这题最恶心的地方是卡空间。 我们先考虑不卡空间时怎么做。 直接并不好做,我们考虑正难则反,即利用容斥原理。答案应为从 a a a 没有任何限制经过 m m m 条

洛谷:P1085 [NOIP2004 普及组] 不高兴的津津

1. 题目链接 https://www.luogu.com.cn/problem/P1085 P1085 [NOIP2004 普及组] 不高兴的津津 2. 题目描述 题目描述:津津每天要上课还要上辅导班,每天学习超过8小时就不开心,帮忙检查下津津的下周日程安排,然后告诉我她哪天不高兴 输入:7行数据,每行2个小于10的非负整数,分别代表在学校的时间和辅导班的时间 输出:哪天最不高兴,如果有

leetcode 二分查找·系统掌握 第一个错误版本

题意: 题解: 就是经典的~01~泛型查找,而且一定存在这样错误的版本所以查找不会"失败",返回每次查找结果即可。 int firstBadVersion(int n) {long l=1,r=n,mid;while(l<r){mid=(l+r)>>1;if(isBadVersion(mid))r=mid;else l=mid+1;}return l;}

leetcode 二分查找·系统掌握 搜索二维矩阵

题目: 题解: 一个可行的思路是使用~01~泛型对每一行的最后一个元素进行查找找到第一个大于等于target的那一行,判断查找结果如果“失败”返回false否则继续在改行进行常规二分查找target的值根据查找结果返回即可。 bool searchMatrix(vector<vector<int>>& matrix, int target) {int l=0,r=matrix.size()-

微策略面试题:在旋转后的数组中查找元素(二分查找)

版权所有。所有权利保留。 欢迎转载,转载时请注明出处: http://blog.csdn.net/xiaofei_it/article/details/17123303 一个无重复元素的有序数组,经过若干次旋转后,得到一个新数组。比如[1,4,5,8,10,12,56,78]变成[12,56,78,1,4,5,8,10]。 现在要在这个数组中寻找元素。 其实算法很简单,就是用二分

【洛谷P3366】【模板】最小生成树 解题报告

洛谷P3366 -【模板】最小生成树 题目描述 如题,给出一个无向图,求出最小生成树,如果该图不连通,则输出 orz。 输入格式 第一行包含两个整数 N , M N,M N,M,表示该图共有 N N N 个结点和 M M M 条无向边。 接下来 M M M 行每行包含三个整数 X i , Y i , Z i X_i,Y_i,Z_i Xi​,Yi​,Zi​,表示有一条长度为 Z