标签:hdu 4630 no pain no 线段树 离线操作
1 10 8 2 4 9 5 7 10 6 1 3 5 2 10 2 4 6 9 1 4 7 10
5 2 2 4 3
题意: 有N个数, 是 1~N的一个排列。有M个询问, 每次询问一个区间, 问从这个区间中,取两个数的最大的最大公约数。
题解:先把查询按右区间升序排序,在将数组按顺序插入,记录当前这个数的因子出现的位置,如果之前有出现则代表这两个因子出现的
位置之间有两个数的公共约数是它,用线段树维护区间约数最大值即可。
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cmath>
#include<vector>
#define lson idx<<1,l,mid
#define rson idx<<1|1,mid+1,r
#define N 50050
#define lc idx<<1
#define rc idx<<1|1
using namespace std;
int n,q,flag;
int a[N],tree[N*4];
int L[N],R[N];
int first[N],ans[N];
vector<int>vec;
struct node {
int id;
int l,r;
} Q[N];
bool cmp(node a,node b) {
if(a.r==b.r)
return a.l<b.l;
return a.r<b.r;
}
///求所有因子
void FJ(int x) {
vec.clear();
for(int i=1; i*i<=x; i++) {
if(x%i==0) {
vec.push_back(i);
if(x/i!=i)
vec.push_back(x/i);
}
}
}
void push_up(int idx) {
tree[idx]=max(tree[lc],tree[rc]);
}
void build(int idx,int l,int r) {
tree[idx]=0;
if(l==r) {
return;
}
int mid=(l+r)>>1;
build(lson);
build(rson);
}
void update(int idx,int l,int r,int x,int v) { //x处的值改为v
if(l==r) {
if(tree[idx]<v)
tree[idx]=v;
return;
}
int mid=(l+r)>>1;
if(x<=mid)update(lson,x,v);
else update(rson,x,v);
push_up(idx);
}
int query(int idx,int l,int r,int x,int y) {
if(l>=x&&y>=r) {
return tree[idx];
}
int ans=0;
int mid=(l+r)>>1;
if(x<=mid) {
ans=max(ans,query(lson,x,y));
}
if(y>mid) {
ans=max(ans,query(rson,x,y));
}
return ans;
}
void debug() {
for(int i=0; i<vec.size(); i++) {
printf("%d ",vec[i]);
}
cout<<endl;
}
int main() {
//freopen("test.in","r",stdin);
int t;
scanf("%d",&t);
while(t--) {
scanf("%d",&n);
for(int i=1; i<=n; i++) {
scanf("%d",&a[i]);
}
scanf("%d",&q);
for(int i=1; i<=q; i++) {
scanf("%d%d",&Q[i].l,&Q[i].r);
Q[i].id=i;
}
sort(Q+1,Q+1+q,cmp);
memset(first,0,sizeof first);
memset(L,0,sizeof L);
memset(R,0,sizeof R);
build(1,1,n);
///预处理相同有区间的左右区间
int f=1;
L[Q[f].r]=f;
R[Q[f].r]=f;
for(int i=1; i<=q;) {
while(Q[i].r==Q[f].r&&i<=q) {
i++;
}
L[Q[f].r]=f;
R[Q[f].r]=i-1;
f=i;
}
for(int i=1; i<=n; i++) {
//FJ(a[i]);
//debug();
int xx=a[i];
for(int k=1; k*k<=xx; k++) {
if(xx%k==0) {
if(!first[k]) {
first[k]=i;
} else {
update(1,1,n,first[k],k);
first[k]=i;
}
int kk=xx/k;
if(k!=kk) {
if(!first[kk]) {
first[kk]=i;
} else {
update(1,1,n,first[kk],kk);
first[kk]=i;
}
}
}
}
int x=L[i],y=R[i];
if(x==0||y==0)continue;
for(int j=x; j<=y; j++) {
int k=Q[j].l;
if(k==i) {
ans[Q[j].id]=0;
} else {
ans[Q[j].id]=query(1,1,n,k,i);
}
}
if(y==q)break;
}
for(int i=1; i<=q; i++) {
printf("%d\n",ans[i]);
}
}
return 0;
}版权声明:本文为博主原创文章,未经博主允许不得转载。
hdu 4630 No Pain No Game(线段树+离线操作)
标签:hdu 4630 no pain no 线段树 离线操作
原文地址:http://blog.csdn.net/acm_baihuzi/article/details/46861217