矩阵图像如下所示。
共个元素。
1. 对称矩阵:
- 一个行列对称矩阵图像特点如下所示:
- 。
- 图像可分为上三角和下三角,两个三角图案全等。
下三角():
上三角()的图差不多就不画了。
我们假设存储下三角的一维数组 (需要的空间,压缩了一半) 是数组,且数组下标从开始。
那么我们的存到数组里的(也是从开始)和有以下关系:
第一部分指的元素个数。
第二部分指第行还有第个。
以存储下三角为例,代码:
#include<bits/stdc++.h>
#define ns "-1"
#define fs(i,x,y,z) for(ll i=x;i<=y;i+=z)
#define ft(i,x,y,z) for(ll i=x;i>=y;i+=z)
#define ll long long
#define ull unsigned long long
#define db double
#define ms(a,b) memset(a,b,sizeof(a))
#define sz(a) sizeof(a)
using namespace std;
const int rw[]={-1,0,1,0,-1,1,-1,1},cl[]={0,1,0,-1,-1,1,1,-1};
const int N=1001,inf=0x7f7f7f7f;
int n,q,a,downsj[N*(N+1)/2];
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cin>>n>>q;
fs(i,1,n,1){
fs(j,1,n,1){
cin>>a;
if(i>=j){
downsj[i*(i-1)/2+j]=a;
}
}
}
fs(i,1,q,1){
int x,y;
cin>>x>>y;
if(x<y) swap(x,y);
cout<<downsj[x*(x-1)/2+y]<<endl;
}
return 0;
}
2. 三角矩阵
三角矩阵分为上三角矩阵和下三角矩阵,这里以下三角为例。
- 一个行列下三角矩阵图像特点如下所示:
- 若(是常数)。
存储方法:
和对称矩阵相同,存储下三角,在询问时若询问上三角就直接回答上三角即可。
以存储下三角为例,代码:
#include<bits/stdc++.h>
#define ns "-1"
#define fs(i,x,y,z) for(ll i=x;i<=y;i+=z)
#define ft(i,x,y,z) for(ll i=x;i>=y;i+=z)
#define ll long long
#define ull unsigned long long
#define db double
#define ms(a,b) memset(a,b,sizeof(a))
#define sz(a) sizeof(a)
using namespace std;
const int rw[]={-1,0,1,0,-1,1,-1,1},cl[]={0,1,0,-1,-1,1,1,-1};
const int N=1001,inf=0x7f7f7f7f;
int n,q,a,downsj[N*(N+1)/2],c;
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cin>>n>>q;
fs(i,1,n,1){
fs(j,1,n,1){
cin>>a;
if(i>=j){
downsj[i*(i-1)/2+j]=a;
}else{
c=a;
}
}
}
fs(i,1,q,1){
int x,y;
cin>>x>>y;
if(x<y) cout<<c<<endl;
else cout<<downsj[x*(x-1)/2+y]<<endl;
}
return 0;
}
那么上三角呢?
我们观察这个矩阵。
会发现,若则。
否则,则和的关系如下所示:
- 第一部分指代中,的个数。
- 第二部分为中中的个数。
代码:
#include<bits/stdc++.h>
#define ns "-1"
#define fs(i,x,y,z) for(ll i=x;i<=y;i+=z)
#define ft(i,x,y,z) for(ll i=x;i>=y;i+=z)
#define ll long long
#define ull unsigned long long
#define db double
#define ms(a,b) memset(a,b,sizeof(a))
#define sz(a) sizeof(a)
using namespace std;
const int rw[]={-1,0,1,0,-1,1,-1,1},cl[]={0,1,0,-1,-1,1,1,-1};
const int N=1001,inf=0x7f7f7f7f;
int n,q,a,downsj[N*(N+1)/2],c;
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cin>>n>>q;
fs(i,1,n,1){
fs(j,1,n,1){
cin>>a;
if(i>j){
c=a;
}else{
downsj[(2*n-i+2)*(i-1)/2+j-i+1]=a;
}
}
}
fs(i,1,q,1){
int x,y;
cin>>x>>y;
if(x>y) cout<<c<<endl;
else cout<<downsj[(2*n-x+2)*(x-1)/2+y-x+1]<<endl;
}
return 0;
}
3. 对角矩阵
对角矩阵的特点如下:
- 基本所有非元素集结在对角线旁,共条对角线(),称为对角矩阵。
则半带宽。
矩阵如下所示:
存储方法:
- 总共需要空间。
- 对于每一条对角线,先补上直到有意义的每一行长度都是。
- Pass掉行前面的个和行最后的个。
- 公式如下所示(
其实我也没理解,老师还打错了,还讲的好好的):
代码:
#include<bits/stdc++.h>
#define ns "-1"
#define fs(i,x,y,z) for(ll i=x;i<=y;i+=z)
#define ft(i,x,y,z) for(ll i=x;i>=y;i+=z)
#define ll long long
#define ull unsigned long long
#define db double
#define ms(a,b) memset(a,b,sizeof(a))
#define sz(a) sizeof(a)
using namespace std;
const int rw[]={-1,0,1,0,-1,1,-1,1},cl[]={0,1,0,-1,-1,1,1,-1};
const int N=1001,inf=0x7f7f7f7f;
int n,q,a,downsj[N*N-2*N],c,d,l;
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cin>>n>>q>>l;d=(l+1)/2;
fs(i,1,n,1){
fs(j,1,n,1){
cin>>a;
if(abs(i-j)>=d){
c=a;
}else{
downsj[(i-1)*l+j-i]=a;
}
}
}
fs(i,1,q,1){
int x,y;
cin>>x>>y;
if(abs(x-y)>=d) cout<<c<<endl;
else cout<<downsj[(x-1)*l+y-x]<<endl;
}
return 0;
}