hdu 4630
算是一道好题目吧,不断地求一段区间的最大公约数,‘|’表示有x这个约数,‘o’表示没有,
|ooo|oo|那么我们可以根据最后一个‘|’的位置来进行在线查询,将要查询的区间按右边界进行排序,更新‘|’的前一个位置。用线段树。。。。。。
//hdu 4630 线段树 #include <iostream> #include <algorithm> #include <cmath> #include <vector> #include <string> #include <cstring> #include <stdio.h> #include <bitset> #include <queue> #define maxn 50002 using namespace std; int num[maxn],pos[maxn],n,m,p[maxn]; vector<int> g[maxn+5]; struct e1 { int x,y,id,ans; }que[maxn]; struct e2 { int l,r,ma; }tree[maxn*6]; bool cmp(e1 a,e1 b) { if(a.y==b.y) return a.x<b.x; return a.y<b.y; } void pushup(int a) { tree[a].ma=max(tree[a*2+1].ma,tree[a*2].ma); } void build(int a,int l,int r) { tree[a].l=l; tree[a].r=r; tree[a].ma=0; if(l==r) return; int mid=(l+r)/2; build(a*2,l,mid); build(a*2+1,mid+1,r); } void insert(int a,int p,int v) { if(tree[a].l==tree[a].r) { tree[a].ma=max(tree[a].ma,v); return; } int mid=(tree[a].l+tree[a].r)/2; if(p<=mid) insert(a*2,p,v); else insert(a*2+1,p,v); pushup(a); } int query(int a,int l,int r) { if(l<=tree[a].l&&tree[a].r<=r) return tree[a].ma; int mid=(tree[a].l+tree[a].r)/2; int ans=0; if(l<=mid) ans=max(query(a*2,l,r),ans); if(mid<r) ans=max(query(a*2+1,l,r),ans); return ans; } int main() { int T,j,k; for(j=1;j<=maxn;j++) for(k=j;k<=maxn;k+=j) g[k].push_back(j); //freopen("d:\\in.txt","r",stdin); scanf("%d",&T); while(T--) { int i,ii,cnt=0; memset(pos,0,sizeof(pos)); scanf("%d",&n); for(i=1;i<=n;i++) scanf("%d",&num[i]); scanf("%d",&m); for(i=0;i<m;i++) { scanf("%d %d",&que[i].x,&que[i].y); que[i].id=i; } sort(que,que+m,cmp); build(1,0,n); for(i=1;i<=n;i++) { int u=num[i]; for(ii=0;ii<g[u].size();ii++) { insert(1,pos[g[u][ii]],g[u][ii]); pos[g[u][ii]]=i; } while(cnt<m&&que[cnt].y==i) { p[que[cnt].id]=query(1,que[cnt].x,que[cnt].y); cnt++; } } for(i=0;i<m;i++) printf("%d\n",p[i]); } return 0; }