两道离线线段树。

比赛时候没想到。。。。

扫描数组,i从1到n,线段树维护从1到i每一个约数(1~50000)的出现的最近位置,线段树存储的是约数的最大值

  1. #include<cstdio>
  2. #include<cstring>
  3. #include<vector>
  4. #include<algorithm>
  5.  
  6. using namespace std;
  7.  
  8. const int N=50050;
  9.  
  10. struct Interval{
  11. int l,r,id;
  12. }in[N];
  13.  
  14. struct Tree{
  15. int l,r,Max;
  16. }tree[N<<2];
  17.  
  18. int n,m;
  19. int a[N];
  20. int pre[N];
  21. int ans[N];
  22. vector<int> factor[N];
  23.  
  24. void init(){
  25. for(int i=1;i<N;i++)
  26. for(int j=i;j<N;j+=i)
  27. factor[j].push_back(i);
  28. }
  29.  
  30. bool cmp(struct Interval a,struct Interval b){
  31. return a.r<b.r;
  32. }
  33.  
  34. void build(int l,int r,int id){
  35. tree[id].l=l;
  36. tree[id].r=r;
  37. tree[id].Max=0;
  38. if(l!=r){
  39. int mid=(l+r)>>1;
  40. build(l,mid,id<<1);
  41. build(mid+1,r,id<<1|1);
  42. }
  43. }
  44.  
  45. void update(int pos,int val,int id){
  46. tree[id].Max=max(tree[id].Max,val);
  47. if(tree[id].l==tree[id].r) return ;
  48. int mid=(tree[id].l+tree[id].r)>>1;
  49. if(mid>=pos) update(pos,val,id<<1);
  50. else update(pos,val,id<<1|1);
  51. }
  52.  
  53. int query(int l,int r,int id){
  54. if(tree[id].l==l && tree[id].r==r) return tree[id].Max;
  55. int mid=(tree[id].l+tree[id].r)>>1;
  56. if(mid>=r) return query(l,r,id<<1);
  57. else if(mid<l) return query(l,r,id<<1|1);
  58. else return max(query(l,mid,id<<1),query(mid+1,r,id<<1|1));
  59. }
  60.  
  61. int main(){
  62. init();
  63. int t,T;
  64. int i,j,k;
  65. scanf("%d",&T);
  66. for(t=1;t<=T;t++){
  67. scanf("%d",&n);
  68. build(1,n,1);
  69. for(i=1;i<=n;i++){
  70. scanf("%d",&a[i]);
  71. }
  72. scanf("%d",&m);
  73. for(i=0;i<m;i++){
  74. scanf("%d %d",&in[i].l,&in[i].r);
  75. in[i].id=i;
  76. }
  77. sort(in,in+m,cmp);
  78. memset(pre,0,sizeof(pre));
  79. for(i=1,j=0;i<=n && j<m;i++){
  80. for(k=0;k<factor[a[i]].size();k++){
  81. int tem=factor[a[i]][k];
  82. if(pre[tem]!=0){
  83. update(pre[tem],tem,1);
  84. }
  85. pre[tem]=i;
  86. }
  87. while(j<m && in[j].r==i){
  88. ans[in[j].id]=query(in[j].l,in[j].r,1);
  89. j++;
  90. }
  91. }
  92. for(i=0;i<m;i++) printf("%d\n",ans[i]);
  93. }
  94. return 0;
  95. }

BOJ的那题找不到了,做完这道题之后,发现这两题很像,都是离线线段树做法。(这道题还是队友出的,膜拜)

先为数组中每个点i一个最小区间l,r满足a[i]>a[l] && a[i]<a[r],l<i<r

然后i从1开始扫描,每次把能加入的点加入,然后处理右端点为i的查询

  1. #include<cstdio>
  2. #include<cstring>
  3. #include<algorithm>
  4. #include<stack>
  5. using namespace std;
  6. const int MAXN = 100000+5;
  7. const int INF = 0x3f3f3f3f;
  8. int T, N, Q, a[MAXN], s[MAXN], t[MAXN];
  9. int idq[MAXN], q[MAXN], cnt[MAXN], p[MAXN];
  10. int x[MAXN], y[MAXN], ida[MAXN];
  11. int Tr[MAXN<<2], mark[MAXN<<2];
  12. void Build(int idx, int L, int R)
  13. {
  14. Tr[idx] = mark[idx] = 0;
  15. if (L == R)
  16. return;
  17. int left = idx<<1, right = idx<<1|1, mid = (L+R)>>1;
  18. Build(left, L, mid);
  19. Build(right, mid+1, R);
  20. }
  21. void PushDown(int idx)
  22. {
  23. int left = idx<<1, right = idx<<1|1, &mk = mark[idx];
  24. Tr[left] += mk;
  25. mark[left] += mk;
  26. Tr[right] += mk;
  27. mark[right] += mk;
  28. mk = 0;
  29. }
  30. void Update(int idx, int L, int R, int l, int r, int c)
  31. {
  32. if (l <= L && R <= r)
  33. {
  34. Tr[idx] += c;
  35. mark[idx] += c;
  36. return;
  37. }
  38. if (mark[idx])
  39. PushDown(idx);
  40. int left = idx<<1, right = idx<<1|1, mid = (L+R)>>1;
  41. if (l <= mid)
  42. Update(left, L, mid, l, r, c);
  43. if (mid < r)
  44. Update(right, mid+1, R, l, r, c);
  45. }
  46. int Query(int idx, int L, int R, int x)
  47. {
  48. if (x == L && R == x)
  49. return Tr[idx];
  50. if (mark[idx])
  51. PushDown(idx);
  52. int left = idx<<1, right = idx<<1|1, mid = (L+R)>>1;
  53. if (x <= mid)
  54. return Query(left, L, mid, x);
  55. else
  56. return Query(right, mid+1, R, x);
  57. }
  58. bool cmpq(const int &a, const int &b)
  59. {
  60. return t[a] < t[b];
  61. }
  62. bool cmpa(const int &a, const int &b)
  63. {
  64. return y[a] < y[b];
  65. }
  66. int main()
  67. {
  68. //freopen("data.in", "r", stdin);
  69. //freopen("data.out", "w", stdout);
  70. scanf("%d", &T);
  71. for (int cas = 1; cas <= T; cas++)
  72. {
  73. printf("Case %d:\n", cas);
  74. scanf("%d", &N);
  75. stack<int> stal, star;
  76. a[0] = 0;
  77. stal.push(0);
  78. for (int i = 1; i <= N; i++)
  79. {
  80. scanf("%d", &a[i]);
  81. while (a[i] <= a[stal.top()])
  82. stal.pop();
  83. x[i] = stal.top();
  84. stal.push(i);
  85. }
  86. a[N+1] = INF;
  87. star.push(N+1);
  88. for (int i = N; i >= 1; i--)
  89. {
  90. while (a[i] >= a[star.top()])
  91. star.pop();
  92. y[i] = star.top();
  93. star.push(i);
  94. ida[i] = i;
  95. }
  96. sort(ida+1, ida+1+N, cmpa);
  97. scanf("%d", &Q);
  98. for (int i = 1; i <= Q; i++)
  99. {
  100. scanf("%d%d", &s[i], &t[i]);
  101. if (s[i] > t[i])
  102. swap(s[i], t[i]);
  103. idq[i] = i;
  104. q[i] = 0;
  105. }
  106. sort(idq+1, idq+1+Q, cmpq);
  107. Build(1, 1, N);
  108. for (int i = 1, j = 1, k = 1; i <= N; i++)
  109. {
  110. for (; y[ida[k]] == i && k <= N; k++) if (x[ida[k]])
  111. Update(1, 1, N, 1, x[ida[k]], 1);
  112. for (; t[idq[j]] == i && j <= Q; j++)
  113. q[idq[j]] = Query(1, 1, N, s[idq[j]]);
  114. }
  115. for (int i = 1; i <= Q; i++)
  116. printf("%d\n", q[i]);
  117. }
  118. return 0;
  119. }

HDU 4630、BOJ 某题的更多相关文章

  1. hdu 4630 查询[L,R]区间内任意两个数的最大公约数

    No Pain No Game Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) ...

  2. HDU - 4630 No Pain No Game (线段树 + 离线处理)

    id=45786" style="color:blue; text-decoration:none">HDU - 4630 id=45786" style ...

  3. HDU 4630 No Pain No Game(2013多校3 1010题 离线处理+树状数组求最值)

    No Pain No Game Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)T ...

  4. HDU 1102 最小生成树裸题,kruskal,prim

    1.HDU  1102  Constructing Roads    最小生成树 2.总结: 题意:修路,裸题 (1)kruskal //kruskal #include<iostream> ...

  5. hdu 4630 No Pain No Game

    http://acm.hdu.edu.cn/showproblem.php?pid=4630 离散化+树状数组 将数组 *a  从后向前遍历 遍历到 a[x] 的时候 再枚举a[x]的约数 假如 约数 ...

  6. HDU 4493 Tutor 水题的收获。。

    题目: http://acm.hdu.edu.cn/showproblem.php?pid=4493 题意我都不好意思说,就是求12个数的平均数... 但是之所以发博客,显然有值得发的... 这个题最 ...

  7. hdu 1853 最小费用流好题 环的问题

    Cyclic Tour Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/65535 K (Java/Others) Tota ...

  8. hdu 4802 GPA 水题

    GPA Time Limit: 20 Sec  Memory Limit: 256 MB 题目连接 http://acm.hdu.edu.cn/showproblem.php?pid=4802 Des ...

  9. hdu 5210 delete 水题

    Delete Time Limit: 1 Sec  Memory Limit: 256 MB 题目连接 http://acm.hdu.edu.cn/showproblem.php?pid=5210 D ...

随机推荐

  1. 比ORA-24777: 我不使用不可移植数据库链接更郁闷的事情达成一致

    现场有一个同步误差,内容如下面:    java.sql.BatchUpdateException: ORA-24777: 不同意使用不可移植的数据库链路    at oracle.jdbc.driv ...

  2. [Android]BaseExpandableListAdapter实现可折叠列表

    使用BaseExpandableListAdapter 以实现的可折叠的所谓列表,例如QQ朋友们在分组功能. 基于BaseExpandableListAdapter扩大ExpandableList说明 ...

  3. projecteuler----&gt;problem=34----Digit factorials

    Problem 34 145 is a curious number, as 1! + 4! + 5! = 1 + 24 + 120 = 145. Find the sum of all number ...

  4. Nyoj Fire Station

    描述A city is served by a number of fire stations. Some residents have complained that the distance fr ...

  5. SSIS从理论到实战,再到应用(5)----流程控制之Foreach循环

    原文:SSIS从理论到实战,再到应用(5)----流程控制之Foreach循环 上期回顾: SSIS从理论到实战,再到应用(4)----流程控制之For循环 上一期讲了For循环,Foreach循环相 ...

  6. MySQL 服务器变量 数据操作DML-视图

    原文:MySQL 服务器变量 数据操作DML-视图 SQL语言的组成部分 常见分类: DDL:数据定义语言 DCL:数据控制语言,如授权 DML:数据操作语言 其它分类: 完整性定义语言: DDL的一 ...

  7. Web字体@font-face对于中文字体的使用

    今天算是刚开始玩博客园..感觉很新鲜在首页 上看到了一个博客http://www.cnblogs.com/liuminghai/p/4238256.html是关于web文字的,挺不错 但是B/S的前端 ...

  8. HTML5实现图片文件异步上传

    原文:HTML5实现图片文件异步上传 利用HTML5的新特点做文件异步上传非常简单方便,本文主要展示JS部分,html结构.下面的代码并未使用第三发库,如果有参照,请注意一些未展现出来的代码片段.我这 ...

  9. 【百度地图API】如何利用自己的数据制作社交地图?只显示可视区域内的标注

    原文:[百度地图API]如何利用自己的数据制作社交地图?只显示可视区域内的标注 摘要:如果你自己的数据已经超过1万个,如何进行合理的显示?除了聚合marker外,还有一个办法.那就是,只显示可视区域内 ...

  10. my97 日期控件

    官网:http://www.my97.net/   好多广告啊! 文档地址: http://www.mysuc.com/test/My97DatePicker/