首页 > 其他分享 >[国家集训队] 矩阵乘法 整体二分

[国家集训队] 矩阵乘法 整体二分

时间:2024-01-17 14:22:46浏览次数:29  
标签:二分 10 int 矩阵 leq ask 国家集训队 乘法

[国家集训队] 矩阵乘法

题目描述

给你一个 \(n \times n\) 的矩阵,不用算矩阵乘法,但是每次询问一个子矩形的第 \(k\) 小数。

输入格式

第一行有两个整数,分别表示矩阵大小 \(n\) 和询问组数 \(q\)。

第 \(2\) 到第 \((n + 1)\) 行,每行 \(n\) 个整数,表示这个矩阵。第 \((i + 1)\) 行的第 \(j\) 个数表示矩阵第 \(i\) 行第 \(j\) 列的数 \(a_{i, j}\)。

接下来 \(q\) 行,每行五个整数 \(x_1, y_1, x_2, y_2, k\),表示一组询问,要求找到以 \((x_1, y_1)\) 为左上角,\((x_2, y_2)\) 为右下角的子矩形中的第 \(k\) 小数。

输出格式

对于每组询问,输出一行一个整数表示答案。

样例 #1

样例输入 #1

2 2
2 1
3 4
1 2 1 2 1
1 1 2 2 3

样例输出 #1

1
3

提示

数据规模与约定

  • 对于 \(20\%\) 的数据,保证 \(n \leq 100\),\(q \leq 10^3\)。
  • 对于 \(40\%\) 的数据,保证 \(n \leq 300\),\(q \leq 10^4\)。
  • 对于 \(60\%\) 的数据,保证 \(n \leq 400\),\(q \leq 3 \times 10^4\)。
  • 对于 \(100\%\) 的数据,保证 \(1 \leq n \leq 500\),\(1 \leq q \leq 6 \times 10^4\),\(0 \leq a_{i, j} \leq 10^9\)。

把整体二分例题朴实无华的扩展到了二维
(还可以上树,直接dfs序就好了)
这个题目能用整体二分的原因我觉得也是差不多的
单个询问能够用二分答案解决,所以能用。
最近写的整体二分的题目的代码我感觉我都调了好久,是因为不专注吗?
不知道

#include<bits/stdc++.h>
#define ll long long
using namespace std;
inline int read() {
	char c=getchar();int a=0,b=1;
	for(;c<'0'||c>'9';c=getchar())if(c=='-')b=-1;
	for(;c>='0'&&c<='9';c=getchar())a=a*10+c-48;return a*b;
}
int tr[501][501],n,m,q_,ans[60001];//¸÷È¡ËùÐèµÄ¸Ð¾õ°É Õâ¸öÆ«Ðò 
inline int lowbit(int x)
{
	return x&(-x);
}
void add(int x,int y,int k)
{
	for(int i=x;i<=n;i+=lowbit(i))
	{
		for(int j=y;j<=n;j+=lowbit(j))
		{
			tr[i][j]+=k;
		}
	}
}
int ask(int x,int y)
{
	int ans=0;
	for(int i=x;i>0;i-=lowbit(i))
		for(int j=y;j>0;j-=lowbit(j))
		{
			ans+=tr[i][j];
		}
	return ans;
}
int ask_(int x1,int y1,int x2,int y2)
{
	return ask(x2,y2)-ask(x1-1,y2)-ask(x2,y1-1)+ask(x1-1,y1-1);
}
struct Matrix
{
	int x,y,v;
}a[250001];
bool mycmp(Matrix a,Matrix b)
{
	if(a.v==b.v&&a.x==b.x)return a.y<b.y;
	if(a.v==b.v)return a.x<b.x;
	return a.v<b.v;
}
struct query
{
	int id,x1,x2,y1,y2,k;
}q[60001],ql[60001],qr[60001];
void solve(int st,int ed,int l,int r)// st denote the start of interval of Martrix,ed the same 
{
	if(l>r)return;
	if(st==ed)
	{
		for(int i=l;i<=r;i++)
		{
			ans[q[i].id]=a[st].v;
		}
		return;
	}
	int mid=(st+ed)>>1;
	for(int i=st;i<=mid;i++)
	{
		add(a[i].x,a[i].y,1);
	}
	int tl=0,tr=0;
	for(int i=l;i<=r;i++)
	{
		int Get=ask_(q[i].x1,q[i].y1,q[i].x2,q[i].y2);
		if(Get<q[i].k)
		{
			qr[++tr]=q[i];
			qr[tr].k-=Get;
		}
		else
		{
			ql[++tl]=q[i];
		}
	}
	for(int i=st;i<=mid;i++)
	{
		add(a[i].x,a[i].y,-1);
	}
	for(int i=l;i<=l+tl-1;i++)
	{
		q[i]=ql[i-l+1];
	}
	for(int i=l+tl;i<=r;i++)
	{
		q[i]=qr[i-l-tl+1];
	}
	solve(st,mid,l,l+tl-1);
	solve(mid+1,ed,l+tl,r);
}
int main()
{
//	freopen("1.in","r",stdin);
//	freopen(".out","w",stdout);
	n=read(),q_=read();int tot=0;
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=n;j++)
		{
			a[++tot].x=i;
			a[tot].y=j;
			a[tot].v=read();
		}
	}
	sort(a+1,a+1+tot,mycmp);
	for(int i=1;i<=q_;i++)
	{
		q[i].x1=read(),q[i].y1=read(),q[i].x2=read(),q[i].y2=read();
		q[i].id=i;q[i].k=read();
	}
	solve(1,tot,1,q_);
	for(int i=1;i<=q_;i++)
	{
		cout<<ans[i]<<endl;
	}
	return 0;
}

这个整体二分是两种写法,一种是把初值当作修改,一种是不当作,我这个是后面这种。
前面那种也可以写。如果这个题目加个修改的话,前面那种可以直接不用大改直接做
然后是二维树状数组熟悉了一下。
没什么了,只是例题而已。
写的还是不够熟练,变量名会写串。。

标签:二分,10,int,矩阵,leq,ask,国家集训队,乘法
From: https://www.cnblogs.com/HLZZPawa/p/17969933

相关文章

  • 算法-二分
    1.整数二分适用于有单调性的数列和部分没有单调性的数列本质:通过一个性质把数列分成两个序列,然后找到分界点注意:每一次循环后数组区间都会变成1,即你所查到的分界点2.实数二分因为没有整除的问题,每次区间都会严格减小一半如果题目要求保留x位小数,则循环条件为r-l<1e-(x+2);......
  • 整体二分 第k大数字
    整体二分,在蓝书上被称为基于值域的整体分治算法我更喜欢叫他整体二分(因为我感觉这样叫更牛逼一点)发现了分治有一个必须满足的性质如果我要把一个区间问题分治,那么这个被分治的区间的前后应该要么是单方面贡献,要么是结果根本不相关,也就是前面的对后面的没有影响其实这个总结非......
  • hdu 4990 Reading comprehension(矩阵乘法)
    Readtheprogrambelowcarefullythenanswerthequestion.pragmacomment(linker,"/STACK:1024000000,1024000000")includeincludeincludeincludeincludeincludeconstintMAX=100000*2;constintINF=1e9;intmain(){intn,m,ans,i;while(sc......
  • 20240113-力扣704二分查找
    leetcode链接:https://leetcode.cn/problems/binary-search/solutions/980494/er-fen-cha-zhao-by-leetcode-solution-f0xw/代码随想录链接:https://programmercarl.com/0704.二分查找.html#算法公开课考点:二分查找解决代码:classSolution{publicintsearch(int[]num......
  • python二分法查找
    比如要在列表arr中查找xdeff(arr,x):left=0right=len(arr)whileleft<right:mid=(left+right)//2ifmid<x:left=midelifmid>x:right=midelse:returnmid......
  • 矩阵乘法 - CF678D Iterated Linear Function
    CF678DIteratedLinearFunction题意\(f_{i,x}=A\timesf_{i-1,x}+B\)且\(f_{0,x}=x\)求\(f_{n,x}\)。思路这道题的递推关系十分清晰。但由于数据范围大(\(1\leA,B,x\le10^9,1\len\le10^{18}\)),所以这道题只能使用矩阵乘法加速递推。矩阵的构造我们需要构造一个......
  • 前缀和,二分 - [ABC203D] Pond
    AT_abc203_DPond题意给出一个\(N\timesN\)的矩阵,然后依次枚举\(k\timesk\)的子矩阵。对于\(k\timesk\)的子矩阵,一共有个\(k^2\)元素,找出其中的中位数。这里的中位数是子矩阵中元素从大到小排列的第$\left\lfloor\frac{k^2}{2}\right\rfloor$个元素。问......
  • 矩阵乘法代码
    voidMatrixChain(intp[],intn,int**m,int**s){for(inti=1;i<=n;i++)m[i][i]=0;//初始化for(intr=2;r<=n;r++){for(inti=1;i<=n-r+1;i++){intj=i+r-1;m[i][j......
  • 递归实现二分
    publicclassBinarySearch{privateint[]array;/***递归实现二分查找*@paramtarget*@return*/publicintsearchRecursion(inttarget){if(array!=null){returnsearchRecursion(target,0,array.lengt......
  • 《算法竞赛》---二分
    整数二分经典模型1.最大值最小化(最大值尽量小)序列划分-----p48#include<bits/stdc++.h>usingnamespacestd;intn,k;//longlongsum;inta[1000000];boolcheck(intx){longlongres=0,cnt=0;res=a[1];for(inti=2;i<=n;i++){if(res+a[i]<......