题目链接: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排序能保证这样处理的结果是正确的。

恩,不错,是一道好题。

 #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=;
int maxx[*maxn], flag[*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[*u]=max(flag[*u],flag[u]);
flag[*u+]=max(flag[*u+],flag[u]);
maxx[*u]=max(maxx[*u],flag[u]);
maxx[*u+]=max(maxx[*u+],flag[u]);
flag[u]=;
}
} 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)>>;
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+,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)>>;
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+,tr);
return max(t1,t2);
}
} void Solve(int x, int r)
{
vt.clear();
vt.push_back(x);
for(int i=; i*i<=x; i++)
if(x%i==)
{
vt.push_back(i);
vt.push_back(x/i);
}
for(int i=; i<vt.size(); i++)
{
int l=pre[ vt[i] ];
pre[ vt[i] ]=r;
if(l==-||l==r) continue;
Update(,,n,l,l,vt[i]);
}
} int main()
{
cin >> T;
while(T--)
{
cin >> n;
for(int i=; i<=n; i++) scanf("%d", a+i), pre[i]=-;
cin >> m;
for(int i=; i<=m; i++) f[i].id=i, scanf("%d%d",&f[i].l,&f[i].r);
sort(f+,f+m+);
for(int i=; i<=*n; i++) maxx[i]=, flag[i]=;
int i=, j=;
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(,,n,f[j].l,f[j].r);
else f[j].ans=;
j++;
}
}
sort(f+,f+m+,cmp);
for(int i=; i<=m; i++)
printf("%d\n",f[i].ans);
}
return ;
}

【HDU4630 No Pain No Game】 dp思想+线段树的离线操作的更多相关文章

  1. [DTOJ3996]:Lesson5!(DP+拓扑+线段树)

    题目描述 “最短的捷径就是绕远路,绕远路就是我最短的捷径” 转眼就$Stage\ X$了,$Stage\ X$的比赛路线可以看做一个$n$个点$m$条边的有向无环图,每条边长度都是$1$.杰洛$\cd ...

  2. Codeforces 675E Trains and Statistic(DP + 贪心 + 线段树)

    题目大概说有n(<=10W)个车站,每个车站i卖到车站i+1...a[i]的票,p[i][j]表示从车站i到车站j所需买的最少车票数,求所有的p[i][j](i<j)的和. 好难,不会写. ...

  3. LightOJ 1085(树状数组+离散化+DP,线段树)

    All Possible Increasing Subsequences Time Limit:3000MS     Memory Limit:65536KB     64bit IO Format: ...

  4. BZOJ 1835: [ZJOI2010]base 基站选址(DP,线段树)

    可以很容易的写出dp方程: F[i][j]=min(F[l][j-1]+w[l][i])+c[i] (w[i][j]是从l+1到i-1这些点p里,所有满足d[p]+s[p]<d[i] & ...

  5. Codeforces 671D Roads in Yusland [树形DP,线段树合并]

    洛谷 Codeforces 这是一个非正解,被正解暴踩,但它还是过了. 思路 首先很容易想到DP. 设\(dp_{x,i}\)表示\(x\)子树全部被覆盖,而且向上恰好延伸到\(dep=i\)的位置, ...

  6. LOJ2537 PKUWC2018 Minimax 树形DP、线段树合并

    传送门 题意:自己去看 首先可以知道,每一个点都有几率被选到,所以$i$与$V_i$的关系是确定了的. 所以我们只需要考虑每一个值的取到的概率. 很容易设计出一个$DP$:设$f_{i,j}$为在第$ ...

  7. 洛谷P3928 Sequence2(dp,线段树)

    题目链接: 洛谷 题目大意在描述底下有.此处不赘述. 明显是个类似于LIS的dp. 令 $dp[i][j]$ 表示: $j=1$ 时表示已经处理了 $i$ 个数,上一个选的数来自序列 $A[0]$ 的 ...

  8. CF 463A && 463B 贪心 && 463C 霍夫曼树 && 463D 树形dp && 463E 线段树

    http://codeforces.com/contest/462 A:Appleman and Easy Task 要求是否全部的字符都挨着偶数个'o' #include <cstdio> ...

  9. [CERC2017]Intrinsic Interval——扫描线+转化思想+线段树

    [CERC2017]Intrinsic Interval https://www.luogu.org/blog/ywycasm/solution-p4747# 这种“好的区间”,见得还是比较多的了. ...

随机推荐

  1. Git的安装与使用

    1,下载git https://code.google.com/p/msysgit/downloads/list 2,安装git ,我们选择命令行形式,这样无论在window下还是在linux下 都可 ...

  2. caffe中添加local层

    下载caffe-local,解压缩; 修改makefile.config:我是将cuudn注释掉,去掉cpu_only的注释; make all make test(其中local_test出错,将文 ...

  3. Http协议提要

    HTTP协议提要 简单来说,HTTP就是一个基于应用层的通信规范:双方要进行通信,大家就要遵守一个规范---HTTP协议.HTTP协议从WWW服务器超文本到本地浏览器 ,可以使浏览器更加高效.HTTP ...

  4. RxJava 的使用入门

    一.什么是 RxJava? RxJava 是一个响应式编程框架,采用观察者设计模式.所以自然少不了 Observable 和 Subscriber 这两个东东了. RxJava 是一个开源项目,地址: ...

  5. AndroidTips:解决Dialog全屏显示以及Dialog显示自动弹出输入法

    继承实现一个dialog,并在onCreate里面做处理. @Override  protected void onCreate(Bundle savedInstanceState) {      s ...

  6. 移动开单扫描终端-全触屏互联网安卓打印扫描 PDAPOS机——开单扫描POS-移动开单扫描POS

    浩瀚云POS是一款自主研发的全触屏互联网POS,一贯以领先的技术.快捷友好的用户体验和在全国广泛覆盖的网络,为电子商务.提供安全.可靠.保密的数据校验服务.作为其研发的一款专业移动开单扫描终端. 互联 ...

  7. D7控件\dw_cd_VirtualTreeview_v4.5.2\Demos\Advanced---TVirtualStringTree用法

    VST1: TVirtualStringTree; //按钮公用函数,根据不同 标签tag区分, Screen.Cursor := crHourGlass; //设置屏幕鼠标的形状为crhourGla ...

  8. Maven的简单使用,HelloWorld

    安装好Maven后就用一个简单的HelloWorld程序来测试一下,体验一下Maven.至于不懂的地方,请查看<Maven实战>书籍. 书籍网址:http://download.csdn. ...

  9. Android系统中的6种模式

    Android系统中的6种模式 1:一般启动模式(normal mode):    功能是正常启动手机,方法为关机状态下按电源键启动. 2:安全模式(safe mode):    此模式和正常启动一样 ...

  10. POJ 2456 (二分)

    题目链接: http://poj.org/problem?id=2456 题目大意:n个房子,m头牛,房子有一个横坐标,问将m头牛塞进房子,每两头牛之间的最大间隔是多少. 解题思路: 不难看出应该二分 ...