1094: 等差区间

Time Limit:5000/3000 MS (Java/Others)   Memory Limit:163840/131072 KB (Java/Others)
Total Submissions:843   Accepted:89

[Submit][Status][Discuss]

Description

已知一个长度为 nn 的数组 a[1],a[2],…,a[n],我们进行 qq 次询问,每次询问区间 a[l],a[l+1],…,a[r−1],a[r],数字从小到大排列后,是否会形成等差数列。等差数列的定义为,数列相邻两项(后一项减去前一项)的差值相等。

Input

本题有多组输入数据。

每组输入数据第一行输入两个正整数 nn 和 qq。第二行输入 nn 个正整数 a[1],a[2],…,a[n]。最后输入 qq 行,每行两个数字 l,rl,r(1≤l≤r≤n),表示询问区间 a[l],…,a[r]。

1≤n,q≤10^5,1≤a[i]≤10^6

Output

对于每组询问输出一行,如果形成等差数列,输出“Yes ”,否则输出“No”(不含引号)。

Sample Input

  1. 5 5
  2. 3 1 5 2 4
  3. 1 3
  4. 4 5
  5. 1 4
  6. 3 4
  7. 2 2

Sample Output

  1. Yes
  2. Yes
  3. No
  4. Yes
  5. Yes
  6.  
  7. 题意:给定一个n位数列,q条查询[l,r],询问子序列[l--r]排序后是否为等差数列。
  8.  
  9. 看题解说用的什么 RMQ求区间最大最小 但是没有学过,过些天再补。我用线段树来代替的求最大最小值。
  10.  
  11. 思路:一个区间要是等差数列:1.所有数相等;2.所有数不等,且求公差,满足g*(r-l)==maxn-minn
  12.  
  13. 然后就是公差,我反正是没想到。求这个序列所有相邻两项差的最大公约数,结果即为公差,求公差也需要在线段树中进行,不能枚举。
  14.  
  15. 同时,需要记录当前这个数上一次出现的位置。
  16.  
  17. 线段树中维护区间:最大值,最小值,公差,序列中所有出现过的数上一次出现的位置的最大值(因为第2中情况需要所有数不同)
  1. #include<iostream>
  2. #include<cstdio>
  3. #include<cstring>
  4. #include<stdlib.h>
  5. using namespace std;
  6. #define lson l,mid,rt<<1
  7. #define rson mid+1,r,rt<<1|1
  8. #define N 100005
  9.  
  10. int num[N];
  11.  
  12. struct Node
  13. {
  14. int l,r;
  15. int maxn,minn,g,lef;
  16. } tree[N<<];
  17.  
  18. int Gcd(int a,int b)
  19. {
  20. if(a==||b==)
  21. return ;
  22. if(a<b)
  23. {
  24. int t=a;
  25. a=b;
  26. b=t;
  27. }
  28. if(a%b==)
  29. return b;
  30. return Gcd(b,a%b);
  31. }
  32.  
  33. int cha[N],loc[N*],last[N];
  34. void build(int l,int r,int rt)
  35. {
  36. tree[rt].maxn=tree[rt].minn=;
  37. tree[rt].l=l;
  38. tree[rt].r=r;
  39. if(l==r)
  40. {
  41. tree[rt].maxn=num[l];
  42. tree[rt].minn=num[l];
  43. tree[rt].g=-;
  44. tree[rt].lef=last[l];
  45. return;
  46. }
  47. int mid=(l+r)>>;
  48. build(lson);
  49. build(rson);
  50. tree[rt].maxn=max(tree[rt<<].maxn,tree[rt<<|].maxn);
  51. tree[rt].minn=min(tree[rt<<].minn,tree[rt<<|].minn);
  52. if(tree[rt<<].l==tree[rt<<].r&&tree[rt<<|].l==tree[rt<<|].r) //建树时求出所有子节点数大于1的结点的公差
  53. tree[rt].g=abs(num[tree[rt<<].r]-num[tree[rt<<|].l]);
  54. else if(tree[rt<<|].l==tree[rt<<|].r)
  55. tree[rt].g=Gcd(tree[rt<<].g,abs(num[tree[rt<<].r]-num[tree[rt<<|].l]));
  56. else
  57. tree[rt].g=Gcd(Gcd(tree[rt<<].g,abs(num[tree[rt<<].r]-num[tree[rt<<|].l])),tree[rt<<|].g);
  58. tree[rt].lef=max(tree[rt<<].lef,tree[rt<<|].lef);
  59. }
  60.  
  61. struct Res
  62. {
  63. int maxn,minn,g,lef;
  64. Res(){}
  65. Res(int a,int b,int g1,int le)
  66. {
  67. maxn=a;
  68. minn=b;
  69. g=g1;
  70. lef=le;
  71. }
  72. };
  73.  
  74. /*Res deal(Res a,Res b)
  75. {
  76. Res tmp(max(a.maxn,b.maxn),min(a.minn,b.minn));
  77. return tmp;
  78. }*/
  79.  
  80. Res query(int L,int R,int l,int r,int rt)
  81. {
  82. if(L==l&&r==R)
  83. {
  84. Res tmp(tree[rt].maxn,tree[rt].minn,tree[rt].g,tree[rt].lef);
  85. return tmp;
  86. }
  87. int mid=(l+r)>>;
  88. if(L>mid)
  89. return query(L,R,rson);
  90. else if(R<=mid)
  91. return query(L,R,lson);
  92. else
  93. {
  94. Res r1=query(L,mid,lson);
  95. Res r2=query(mid+,R,rson);
  96. Res r3;
  97. r3.maxn=max(r1.maxn,r2.maxn);
  98. r3.minn=min(r1.minn,r2.minn);
  99. if(r1.g==-&&r2.g==-) //查询时需注意,若查到叶子结点,其公约数为-1,需特殊处理
  100. r3.g=abs(num[mid]-num[mid+]);
  101. else if(r1.g==-)
  102. r3.g=Gcd(abs(num[mid]-num[mid+]),r2.g);
  103. else if(r2.g==-)
  104. r3.g=Gcd(abs(num[mid]-num[mid+]),r1.g);
  105. else
  106. r3.g=Gcd(r1.g,Gcd(abs(num[tree[rt<<].r]-num[tree[rt<<|].l]),r2.g));
  107. r3.lef=max(r1.lef,r2.lef);
  108. return r3;
  109. }
  110. }
  111.  
  112. int main()
  113. {
  114. int n,q;
  115. while(scanf("%d%d",&n,&q)!=EOF)
  116. {
  117. //memset(tree,0,sizeof(tree));
  118. memset(loc,,sizeof(loc));
  119. for(int i=; i<=n; i++)
  120. {
  121. scanf("%d",&num[i]);
  122. if(loc[num[i]]==)
  123. last[i]=;
  124. else
  125. last[i]=loc[num[i]];
  126. loc[num[i]]=i;
  127. if(i>)
  128. cha[i-]=abs(num[i]-num[i-]);
  129. }
  130.  
  131. build(,n,);
  132. while(q--)
  133. {
  134. int ll,rr;
  135. scanf("%d%d",&ll,&rr);
  136. Res tm=query(ll,rr,,n,);
  137. int maxn=tm.maxn;
  138. int minn=tm.minn;
  139. int g=tm.g;
  140. int lef=tm.lef;
  141. //cout<<maxn<<' '<<minn<<' '<<g<<' '<<lef<<endl;
  142. if(minn==maxn)
  143. {
  144. printf("Yes\n");
  145. continue;
  146. }
  147. if(lef<ll&&(g*(rr-ll)==maxn-minn))
  148. printf("Yes\n");
  149. else
  150. printf("No\n");
  151. }
  152. }
  153. return ;
  154. }
  1.  RMQRange Minimum/Maximum Query),即区间最值查询。一种动态规划。思路和线段树的一样。
  1. #include<iostream>
  2. #include<cstring>
  3. #include<cstdio>
  4. #include<cmath>
  5. #include<stdlib.h>
  6. using namespace std;
  7. #define N 100005
  8.  
  9. int dpMax[N][],dpMin[N][],dpG[N][],dpLeft[N][],n,loc[N*];
  10.  
  11. int Gcd(int a,int b)
  12. {
  13. if(a==||b==)
  14. return ;
  15. if(a<b)
  16. {
  17. int tmp=a;
  18. a=b;
  19. b=tmp;
  20. }
  21. if(a%b==)
  22. return b;
  23. return Gcd(b,a%b);
  24. }
  25.  
  26. void RMQ()
  27. {
  28. for(int j=; j<=; j++)
  29. for(int i=; i<=n; i++)
  30. if((<<j)+i-<=n)
  31. {
  32. dpMax[i][j]=max(dpMax[i][j-],dpMax[i+(<<j-)][j-]);
  33. dpMin[i][j]=min(dpMin[i][j-],dpMin[i+(<<j-)][j-]);
  34. dpLeft[i][j]=max(dpLeft[i][j-],dpLeft[i+(<<j-)][j-]);
  35. if(j==)
  36. dpG[i][j]=abs(dpMin[i][]-dpMin[i+][]);
  37. else
  38. dpG[i][j]=Gcd(dpG[i][j-],Gcd(abs(dpMin[i+(<<j-)][]-dpMin[i+(<<j-)-][]),dpG[i+(<<j-)][j-]));
  39. }
  40. }
  41.  
  42. int main()
  43. {
  44. //cout<<log2(0)<<endl;
  45. int q;
  46. while(scanf("%d%d",&n,&q)!=EOF)
  47. {
  48. memset(loc,,sizeof(loc));
  49. for(int i=; i<=n; i++)
  50. {
  51. scanf("%d",&dpMin[i][]);
  52. dpMax[i][]=dpMin[i][];
  53. dpG[i][]=-;
  54. if(loc[dpMin[i][]]==)
  55. dpLeft[i][]=;
  56. else
  57. dpLeft[i][]=loc[dpMin[i][]];
  58. loc[dpMin[i][]]=i;
  59. }
  60. RMQ();
  61. while(q--)
  62. {
  63. int l,r;
  64. scanf("%d%d",&l,&r);
  65. int k=log2(r-l+);
  66. int maxn=max(dpMax[l][k],dpMax[r-(<<k)+][k]);
  67. int minn=min(dpMin[l][k],dpMin[r-(<<k)+][k]);
  68. int left=max(dpLeft[l][k],dpLeft[r-(<<k)+][k]);
  69. int g=abs(dpMin[l][]-dpMin[r][]);
  70. if(r-l>)
  71. g=Gcd(g,Gcd(dpG[l][k],dpG[r-(<<k)+][k]));
  72. //cout<<maxn<<' '<<minn<<' '<<g<<' '<<left<<endl;
  73. if(maxn==minn)
  74. printf("Yes\n");
  75. else
  76. {
  77. if(left<l&&maxn-minn==(r-l)*g)
  78. printf("Yes\n");
  79. else
  80. printf("No\n");
  81. }
  82. }
  83. }
  84. return ;
  85. }
  1.  

dutacm.club_1094_等差区间_(线段树)(RMQ算法)的更多相关文章

  1. BZOJ_4653_[Noi2016]区间_线段树+离散化+双指针

    BZOJ_4653_[Noi2016]区间_线段树+离散化+双指针 Description 在数轴上有 n个闭区间 [l1,r1],[l2,r2],...,[ln,rn].现在要从中选出 m 个区间, ...

  2. BZOJ_2124_等差子序列_线段树+Hash

    BZOJ_2124_等差子序列_线段树+Hash Description 给一个1到N的排列{Ai},询问是否存在1<=p1<p2<p3<p4<p5<…<pL ...

  3. CSU 1809 - Parenthesis - [前缀和+维护区间最小值][线段树/RMQ]

    题目链接:http://acm.csu.edu.cn/csuoj/problemset/problem?pid=1809 Bobo has a balanced parenthesis sequenc ...

  4. [bzoj2124]等差子序列_线段树_hash

    等差子序列 bzoj-2124 题目大意:给定一个1~n的排列,问是否存在3个及以上的位置上的数构成连续的等差子序列. 注释:$1\le n\le 10^4$. 想法:这题就相当于是否存在3个数i,j ...

  5. BZOJ_4636_蒟蒻的数列_线段树+动态开点

    BZOJ_4636_蒟蒻的数列_线段树+动态开点 Description 蒟蒻DCrusher不仅喜欢玩扑克,还喜欢研究数列 题目描述 DCrusher有一个数列,初始值均为0,他进行N次操作,每次将 ...

  6. BZOJ_3252_攻略_线段树+dfs序

    BZOJ_3252_攻略_线段树+dfs序 Description 题目简述:树版[k取方格数] 众所周知,桂木桂马是攻略之神,开启攻略之神模式后,他可以同时攻略k部游戏.今天他得到了一款新游戏< ...

  7. BZOJ_1826_[JSOI2010]缓存交换 _线段树+贪心

    BZOJ_1826_[JSOI2010]缓存交换 _线段树+贪心 Description 在计算机中,CPU只能和高速缓存Cache直接交换数据.当所需的内存单元不在Cache中时,则需要从主存里把数 ...

  8. BZOJ_1828_[Usaco2010 Mar]balloc 农场分配_线段树

    BZOJ_1828_[Usaco2010 Mar]balloc 农场分配_线段树 Description Input 第1行:两个用空格隔开的整数:N和M * 第2行到N+1行:第i+1行表示一个整数 ...

  9. BZOJ_1858_[Scoi2010]序列操作_线段树

    BZOJ_1858_[Scoi2010]序列操作_线段树 Description lxhgww最近收到了一个01序列,序列里面包含了n个数,这些数要么是0,要么是1,现在对于这个序列有五种变换操作和询 ...

随机推荐

  1. C# .NET Visual Studio VS2008如何显示行号

    工具-选项,然后勾选"显示所有设置",然后在文本编辑器下面找到所有语言,勾选"行号"即可.  

  2. [Android Studio] 取消引用库打包出现异常-- provided dependencies can only be jars

    Warning: Project App: provided dependencies can only be jars. com.android.support:appcompat-v7:22.2. ...

  3. HDU5465/BestCoder Round #56 (div.2) 二维树状数组

    Clarke and puzzle 问题描述 克拉克是一名人格分裂患者.某一天,有两个克拉克(aa和bb)在玩一个方格游戏. 这个方格是一个n*mn∗m的矩阵,每个格子里有一个数c_{i, j}c​i ...

  4. BZOJ 1037: [ZJOI2008]生日聚会Party 四维DP

    1037: [ZJOI2008]生日聚会Party Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 1650  Solved: 971[Submit][ ...

  5. 危险的input 微博的过去

    更改uid post地址不变

  6. SQl 事物+视图+游标+索引+锁

    一:事务: 是访问并可能更新数据库中各种数据项的一个程序执行单元(unit),事务是恢复和并发控制的基本单位. 事务的四个特性:ACID A:atomicity 原子性,事务里的所有操作都是一体的,要 ...

  7. html5 canvas程序演示--P1197 [JSOI2008]星球大战

    html5 canvas程序演示--P1197 [JSOI2008]星球大战 <!doctype html> <html> <head> <meta char ...

  8. python 视频逐帧保存为图片

    import cv2 import os def save_img(): video_path = r'F:\test\video1/' videos = os.listdir(video_path) ...

  9. openStack Aio 环境的neutron agent-list和cluster 环境 CLI结果对比

  10. HashMap1

    一.Java并发基础 当一个对象或变量可以被多个线程共享的时候,就有可能使得程序的逻辑出现问题. 在一个对象中有一个变量i=0,有两个线程A,B都想对i加1,这个时候便有问题显现出来,关键就是对i加1 ...