您的位置:首页 > 大数据 > 人工智能

2013多校联合3 1010 No Pain No Game(hdu 4630)

2013-07-30 20:09 405 查看
http://acm.hdu.edu.cn/showproblem.php?pid=4630


No Pain No Game

Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)

Total Submission(s): 72    Accepted Submission(s): 21


Problem Description

Life is a game,and you lose it,so you suicide.

But you can not kill yourself before you solve this problem:

Given you a sequence of number a1, a2, ..., an.They are also a permutation of 1...n.

You need to answer some queries,each with the following format:

If we chose two number a,b (shouldn't be the same) from interval [l, r],what is the maximum gcd(a, b)? If there's no way to choose two distinct number(l=r) then the answer is zero.

 

Input

First line contains a number T(T <= 5),denote the number of test cases.

Then follow T test cases.

For each test cases,the first line contains a number n(1 <= n <= 50000).

The second line contains n number a1, a2, ..., an.

The third line contains a number Q(1 <= Q <= 50000) denoting the number of queries.

Then Q lines follows,each lines contains two integer l, r(1 <= l <= r <= n),denote a query.

 

Output

For each test cases,for each query print the answer in one line.

 

思路:设数列为a[1]~a
,我们·‚从左往右扫描,依次加入a[i],我们设r为当前位置,po[x]为当前位置之前,有因数x的数所出现的位置中,最靠右的那个位置,设dp[i]为位置i到当前为位置r之间(也就是区间[i,r])GCD的最大值,则我们枚举a[i]的所有因数xi,则我们可以将区间[1,po[xi]]中所有小于xi的dp项赋值为xi,这可以用线段树来维护,更新后再将po[xi]=r,那么枚举玩a[i]的所有因数后,我们可以知道对于所有l(l<=r)区间[l,r]中GCD的最大值。所以我们需要一开始将1到50000的所有因数求出来,并且将询问按照R从小到大排序,离线处理即可。以下是代码。

线段树写的很挫,G++还TLE了,C++1700ms卡过。。。仅供参考。。。

#include <iostream>
#include <string.h>
#include <stdio.h>
#include <algorithm>
#include <vector>
#define maxn 50010
#define mid ((t[p].l+t[p].r)>>1)
#define ls (p<<1)
#define rs (ls|1)
using namespace std;
struct tree
{
int l,r;
int lazy;
}t[maxn<<2];
void pushdown(int p)
{
if(t[p].lazy)
{
t[ls].lazy=max(t[ls].lazy,t[p].lazy);
t[rs].lazy=max(t[rs].lazy,t[p].lazy);
t[p].lazy=0;
}
}
void build(int p,int l,int r)
{
t[p].l=l,t[p].r=r,t[p].lazy=0;
if(l==r)
{
return;
}
build(ls,l,mid);
build(rs,mid+1,r);
}
void change(int p,int l,int r,int val)
{
if(t[p].l==l&&t[p].r==r)
{
t[p].lazy=max(t[p].lazy,val);
return;
}
pushdown(p);
if(l>mid)
change(rs,l,r,val);
else if(r<=mid)
change(ls,l,r,val);
else
{
change(ls,l,mid,val);
change(rs,mid+1,r,val);
}
}
int query(int p,int x)
{
if(t[p].l==t[p].r)
return t[p].lazy;
pushdown(p);
if(x>mid)
return query(rs,x);
else
return query(ls,x);
}
vector<int> vec[maxn];
void init()
{
int i;
for(i=1;i<=50000;i++)
{
for(int j=i;j<=50000;j+=i)
{
vec[j].push_back(i);
}
}
}
int po[maxn],a[maxn],ans[maxn];
struct ask
{
int num;
int l,r;
}as[maxn];
bool cmp(ask a,ask b)
{
return a.r<b.r;
}
int main()
{
// freopen("dd.txt","r",stdin);
init();
int ncase;
scanf("%d",&ncase);
while(ncase--)
{
int n,i,q;
scanf("%d",&n);
build(1,1,n);
for(i=1;i<=n;i++)
{
scanf("%d",&a[i]);
po[i]=0;
}
scanf("%d",&q);
for(i=1;i<=q;i++)
{
scanf("%d%d",&as[i].l,&as[i].r);
as[i].num=i;
}
sort(as+1,as+q+1,cmp);
int qnum=1;
as[q+1].r=maxn;
for(i=1;i<=n;i++)
{
for(int j=0;j<vec[a[i]].size();j++)
{
int tmp=vec[a[i]][j];
if(po[tmp])
{
change(1,1,po[tmp],tmp);
}
po[tmp]=i;
}
while(as[qnum].r<=i)
{
ans[as[qnum].num]=query(1,as[qnum].l);
qnum++;
}
if(qnum>q)
break;
}
for(i=1;i<=q;i++)
{
printf("%d\n",ans[i]);
}
}
return 0;
}



                                            
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: