思路:这题是问一个矩阵由一直规律的画j形递增数组组成
1 12 125
43 436
987
问给一个数组,求他在哪行哪列
这题其实就是数列,我们从上往下看矩阵的每行的第一个元素规律是
1 (+3) 4 (+5) 9 (+7) 16 …(+t) num
所以需要初始化维护两个集合
一个是每行第一个数字的索引。h[1]=1 h[2]=4 h[3]=9…
一个是每行所构成的集合也就是J形的集合有多少个元素 s[1]=1 s[2]=3 s[3]=5…
然后就能通过这两个集合O(logn)找到答案
假设问x的位置
我们只需要二分h[]就能找到x的位置,这个位置就是他的j形数组所在位置。
然后只需要用s[] 来判断他是不是在横线还是竖线上即可。
#include <iostream>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;
const int N = 50010;
vector<int> h;
int s[N];
inline void init()
{
int n=0;
int num=1;
int t=1;
h.push_back(0);
s[0]=0;
while(num<=1e9+10)
{
h.push_back(num);
s[++n]=t;
t+=2;
num+=t;
}
//cout<<num<<" "<<t<<" "<<s[]<<endl;
h.push_back(num);
s[++n]=t;
t+=2;
}
inline int find(int x)
{
return lower_bound(h.begin(), h.end(), x) - h.begin();
}
inline void get(int x)
{
int idx=find(x);
int maxa=h[idx],mina=h[idx]-s[idx]+1;
//cout<<x<<" === "<<idx<<" "<<h[idx]<<" "<<s[idx]<<endl;
int col=1,row=idx;
if(maxa-s[idx]/2<=x)
{
//cout<<" maxa-s[idx]/2 = "<<(maxa-s[idx]/2)<<endl;
col=maxa-x+1;
}
else
{
col=s[idx]/2+1;
row=x-mina+1;
}
cout<<row<<" "<<col<<endl;
}
int main() {
int T,x;
init();
cin >> T;
while (T--) {
cin>>x;
get(x);
}
return 0;
}