【HDU4630 No Pain No Game】 dp思想+线段树的离线操作
2013-08-04 14:20
211 查看
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4630
题意:给你n个数据范围在[1,n]中的数,m个操作,每个操作一个询问[L,R],让你求区间[L,R]内任意两个数的最大公倍数。
思路:是线段树是必然的 O.O 。顺着来不好解决,只能离线处理试试。按r从小到大排序,数组a[i]从左到右扫一遍,对每个a[i]都要进行处理,先因数分解,pre[X]表示约数X在前面最后出现的位置。开始处理的是pre[X]到当前位置r都对约数X进行比较更新,后面想想这样是有问题,因为这样不能保证约数X出现在pre[X]与r的中间位置,所以这里我们只对位置pre[X]进行最大约数的比较更新,这样就能很好的解决当询问[pre[X],r]时,这个约数恰好就出现在区间段内,pre[X]更新为r,起初的对询问区间段r排序能保证这样处理的结果是正确的。
恩,不错,是一道好题。
View Code
题意:给你n个数据范围在[1,n]中的数,m个操作,每个操作一个询问[L,R],让你求区间[L,R]内任意两个数的最大公倍数。
思路:是线段树是必然的 O.O 。顺着来不好解决,只能离线处理试试。按r从小到大排序,数组a[i]从左到右扫一遍,对每个a[i]都要进行处理,先因数分解,pre[X]表示约数X在前面最后出现的位置。开始处理的是pre[X]到当前位置r都对约数X进行比较更新,后面想想这样是有问题,因为这样不能保证约数X出现在pre[X]与r的中间位置,所以这里我们只对位置pre[X]进行最大约数的比较更新,这样就能很好的解决当询问[pre[X],r]时,这个约数恰好就出现在区间段内,pre[X]更新为r,起初的对询问区间段r排序能保证这样处理的结果是正确的。
恩,不错,是一道好题。
#include <iostream> #include <cstdio> #include <cstring> #include <vector> #include <algorithm> using namespace std; #define lz 2*u,l,mid #define rz 2*u+1,mid+1,r const int maxn=50005; int maxx[4*maxn], flag[4*maxn]; int a[maxn]; int pre[maxn]; int n, m, T; vector<int>vt; struct node { int l, r, id; int ans; friend bool operator<(const node A, const node B) { return A.r<B.r; } }f[maxn]; bool cmp(node A, node B) { return A.id<B.id; } void push_down(int u, int l, int r) { if(flag[u]) { flag[2*u]=max(flag[2*u],flag[u]); flag[2*u+1]=max(flag[2*u+1],flag[u]); maxx[2*u]=max(maxx[2*u],flag[u]); maxx[2*u+1]=max(maxx[2*u+1],flag[u]); flag[u]=0; } } void Update(int u, int l, int r, int tl, int tr, int val) { maxx[u]=max(maxx[u],val); if(tl<=l&&r<=tr) { flag[u]=max(flag[u],val); maxx[u]=max(maxx[u],val); return ; } push_down(u,l,r); int mid=(l+r)>>1; if(tr<=mid) Update(lz,tl,tr,val); else if(tl>mid) Update(rz,tl,tr,val); else { Update(lz,tl,mid,val); Update(rz,mid+1,tr,val); } } int Query(int u, int l, int r, int tl, int tr) { if(tl<=l&&r<=tr) return maxx[u]; push_down(u,l,r); int mid=(l+r)>>1; if(tr<=mid) return Query(lz,tl,tr); else if(tl>mid) return Query(rz,tl,tr); else { int t1=Query(lz,tl,mid); int t2=Query(rz,mid+1,tr); return max(t1,t2); } } void Solve(int x, int r) { vt.clear(); vt.push_back(x); for(int i=2; i*i<=x; i++) if(x%i==0) { vt.push_back(i); vt.push_back(x/i); } for(int i=0; i<vt.size(); i++) { int l=pre[ vt[i] ]; pre[ vt[i] ]=r; if(l==-1||l==r) continue; Update(1,1,n,l,l,vt[i]); } } int main() { cin >> T; while(T--) { cin >> n; for(int i=1; i<=n; i++) scanf("%d", a+i), pre[i]=-1; cin >> m; for(int i=1; i<=m; i++) f[i].id=i, scanf("%d%d",&f[i].l,&f[i].r); sort(f+1,f+m+1); for(int i=1; i<=4*n; i++) maxx[i]=1, flag[i]=0; int i=1, j=1; while(j<=m) { if(i<=f[j].r&&i<=n) { Solve(a[i],i); i++; } else { if(f[j].l!=f[j].r)f[j].ans=Query(1,1,n,f[j].l,f[j].r); else f[j].ans=0; j++; } } sort(f+1,f+m+1,cmp); for(int i=1; i<=m; i++) printf("%d\n",f[i].ans); } return 0; }
View Code
相关文章推荐
- hdu3874(离线思想+线段树)
- HDU 4288 Coder (技巧性暴力模拟+二分||线段树+离线操作)
- HDU 4521 2013腾讯编程马拉松初赛第四场 小明系列问题——小明序列(dp思想+线段树优化)
- HDU 4417 Super Mario(线段树||树状数组+离线操作 之线段树篇)
- [树状数组&线段树]HDU3874 Necklace 离线思想
- hdu 3874 Necklace(离线操作+树状数组或线段树)
- 线段树区间更新操作及Lazy思想(详解)
- hdu 4521 小明序列(线段树,DP思想)
- uva297 Quadtrees (线段树思想,区间操作)
- HDU4417 Super Mario 线段树离线操作
- ACM学习历程——HDU3333 Turing Tree(线段树 && 离线操作)
- hdu 4358 Boring counting 线段树离线操作
- 【HDU4288 Coder】离线+离散化+5颗线段树的更新操作
- 2015暑假训练(UVALive 5983 - 5992)线段树离线处理+dp+floyed最短路
- Necklace (线段树单点更新+区间查询+离线操作)
- BZOJ2333 [SCOI2011]棘手的操作 【离线 + 线段树】
- 线段树成段更新操作及Lazy思想(POJ3468解题报告)
- UVa 11402 Ahoy, Pirates!(线段树 + 离线操作)
- SPOJ--K-query (线段树离线) 离线操作解决一些问题
- 树链剖分-链的剖分(线段树维护+离线操作)