【题目大意】
给一个有n个元素数组a[]。定义F(l,r) == gcd(ai);1 <= l <= r <= n。
给了一个计算RANK(l,r)的函数,返回值是一个pair,(k1,k2)
两种询问,1、已知l,r,求k1,k2;2、已知k1,k2,求l,r。
【思路】
若l固定,r从l增大到n。其F()值会越来越小,而且,后者一定会是前者的一个因子。所以l固定,F()值的种类最多分为log(n-l)种。这就是解题的关键。
想到分段了后,这题其实就不是很难了,感觉会有各种各样的解法,就是有点麻烦。下面说我怎么做的。
如果l固定,我们将F()分段。这里对应代码中的node结构体,一个node的意思是(l,r1...r2)的F()值都为g。
我们按g值相同的段,放到一起。排序第一关键字为l,第二为r2(r1也行)。
(一)已知l,r,求k1,k2。这里先要求F(l,r),这里有多种方法,随便搞搞就能解出来了。如果F(l,r)== g ,k1等于F()值小于g值的种类+1,这也是很好求的。又,因为我们把g值相同的段放在一起,利用二分,很容易求出来k2。
(二)已知k1,k2,,求l,r。利用二分,很容易得到答案的g值(即F())。g值确定了,答案(l,r)其实就是这一类的第k2个区间。
//#pragma comment(linker, "/STACK:102400000,102400000")
#include<cstdio>
#include<cstring>
#include<vector>
#include<queue>
#include<cmath>
#include<cctype>
#include<string>
#include<algorithm>
#include<iostream>
#include<ctime>
#include<map>
#include<set>
using namespace std;
#define MP(x,y) make_pair((x),(y))
#define PB(x) push_back(x)
typedef long long LL;
typedef unsigned long long ULL;
/* ****************** */
const int INF = 100011122;
const double INFF = 1e100;
const double eps = 1e-8;
const LL mod = 20140518;
const int NN = 100010;
const int MM = 5000010;
/* ****************** */
struct node1
{
int r, g;
node1(int a = 0,int b = 0):r(a), g(b){}
bool operator<(const node1 &tt)const
{
return r < tt.r;
}
bool operator==(const node1 &tt)const
{
return (r == tt.r);
}
};
vector<node1>bb[NN];
struct node
{
int l,r1,r2,g;
node(int a = 0,int b = 0,int c = 0,int d = 0): l(a), r1(b), r2(c), g(d){}
bool operator<(const node &tt)const
{
if(l == tt.l)
{
return r2 < tt.r2;
}
return l < tt.l;
}
bool operator==(const node &tt)const
{
return (l == tt.l) && (r2 == tt.r2);
}
};
vector<node> aa[NN];
vector<LL> ge[NN];
node sta[NN];
LL sum[NN];
int a[NN];
int gcd(int a,int b)
{
if(b == 0) return a;
return gcd(b, a%b);
}
void solve(int n,int m,int max_g)
{
char op[15];
LL k1, k2;
int g, l, r, temp;
while(m--)
{
scanf("%s", op);
if(op[0] == 'R')
{
scanf("%d%d",&l, &r);
g = lower_bound(bb[l].begin(), bb[l].end(), node1(r, 0)) -> g;
k1 = sum[g-1];
temp = upper_bound(aa[g].begin(), aa[g].end(), node(l, l, r, 0)) - aa[g].begin();
if(temp == 0)
k2 = 0;
else
k2 = ge[g][temp-1];
if(temp < (int)ge[g].size() && l == aa[g][temp].l && r >= aa[g][temp].r1)
{
k2 += r - aa[g][temp].r1 + 1;
}
k1++;
printf("%I64d %I64d\n",k1, k2);
}
else
{
scanf("%I64d%I64d",&k1, &k2);
k1--;
g = upper_bound(sum+1, sum+1+max_g, k1) - sum;
if(g > max_g || sum[g-1] != k1 || ge[g][ ge[g].size() - 1 ] < k2)
{
puts("-1");
continue;
}
temp = upper_bound(ge[g].begin(), ge[g].end(), k2-1) - ge[g].begin();
if(temp > 0)
k2 -= ge[g][temp-1];
l = aa[g][temp].l;
r = aa[g][temp].r1 + k2 - 1;
printf("%d %d\n",l, r);
}
}
}
int main()
{
int cas, ee = 0;
int n, m, i, j, tail, tol, temp;
int max_g;
bool fg;
LL pre;
scanf("%d", &cas);
while(cas--)
{
scanf("%d%d", &n, &m);
for(i = 1; i <= n; i ++)
scanf("%d", &a[i]);
max_g = 0;
tail = 0;
for(i = n; i >= 1; i --)
{
sta[++tail] = node(i, i, i, a[i]);
for(j = tail - 1; j >= 1; j --)
{
sta[j].l --;
sta[j].g = gcd(sta[j].g, a[i]);
}
tol = 1;
for(j = 2; j <= tail; j ++)
{
if(sta[j].g == sta[tol].g)
{
sta[tol].r1 = sta[j].r1;
}
else
{
sta[++tol] = sta[j];
}
}
tail = tol;
for(j = 1; j <= tail; j ++)
{
max_g = max(max_g, sta[j].g);
aa[ sta[j].g ].PB( sta[j] );
}
for(j = tail; j >= 1; j --)
{
bb[i].PB( node1(sta[j].r2, sta[j].g) );
}
}
sum[0] = 0;
for(i = 1; i <= max_g; i ++)
{
tol = aa[i].size();
sum[i] = sum[i-1];
for(j = 0; j < tol/2; j ++)
{
swap(aa[i][j], aa[i][tol-1-j]);
}
pre = 0;
fg = false;
for(j = 0; j < tol; j ++)
{
temp = aa[i][j].r2 - aa[i][j].r1 + 1;
if(temp)
fg = true;
ge[i].PB(temp + pre);
pre += temp;
}
if(fg) sum[i]++;
}
printf("Case #%d:\n", ++ee);
solve(n, m, max_g);
for(i = 1; i <= max_g; i ++)
{
aa[i].clear();
ge[i].clear();
}
for(i = 1; i <= n; i ++)
{
bb[i].clear();
}
}
return 0;
}