题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4373

一个区间有以 k 为公差的数列,有3个条件:

1.区间 mx - mn = (r-l) * k;

2.差分数组的 gcd 是 k 的倍数;

3.没有重复出现的数;

其中1,2都可以用线段树维护,3用 set 维护每个数上一个出现的位置即可;

模仿TJ写的:https://blog.csdn.net/neither_nor/article/details/52461940

对 set 更熟悉了,细节还蛮多的。

代码如下:

  1. #include<iostream>
  2. #include<cstdio>
  3. #include<cstring>
  4. #include<set>
  5. #include<map>
  6. using namespace std;
  7. int const maxn=3e5+;
  8. int n,m,a[maxn],key,tot,pre[maxn];
  9. map<int,int>h;
  10. set<int>s[maxn<<];
  11. int gcd(int a,int b){return b?gcd(b,a%b):a;}
  12. int ab(int x){return x>?x:-x;}
  13. struct N{
  14. int mx,mn,fro,g;
  15. friend N operator + (N x,N y)
  16. {
  17. N ret;
  18. ret.mx=max(x.mx,y.mx);
  19. ret.mn=min(x.mn,y.mn);
  20. ret.fro=max(x.fro,y.fro);
  21. ret.g=gcd(x.g,y.g);
  22. return ret;//!
  23. }
  24. }t[maxn<<];
  25. void build(int x,int l,int r)
  26. {
  27. if(l==r)
  28. {
  29. t[x].mn=t[x].mx=a[l]; t[x].g=ab(a[l+]-a[l]);
  30. t[x].fro=pre[l]; return;
  31. }
  32. int mid=((l+r)>>);
  33. build(x<<,l,mid); build(x<<|,mid+,r);
  34. t[x]=t[x<<]+t[x<<|];
  35. }
  36. void update(int x,int l,int r,int p)
  37. {
  38. if(l==r)
  39. {
  40. t[x].mn=t[x].mx=a[l]; t[x].g=ab(a[l+]-a[l]);
  41. t[x].fro=pre[l]; return;
  42. }
  43. int mid=((l+r)>>);
  44. if(p<=mid)update(x<<,l,mid,p);
  45. else update(x<<|,mid+,r,p);
  46. t[x]=t[x<<]+t[x<<|];
  47. }
  48. N query(int x,int l,int r,int L,int R)
  49. {
  50. if(l>=L&&r<=R)return t[x];
  51. int mid=((l+r)>>);
  52. if(mid<L)return query(x<<|,mid+,r,L,R);
  53. else if(mid>=R)return query(x<<,l,mid,L,R);
  54. else return query(x<<,l,mid,L,R)+query(x<<|,mid+,r,L,R);
  55. }
  56. int main()
  57. {
  58. scanf("%d%d",&n,&m);
  59. for(int i=;i<=n;i++)
  60. {
  61. scanf("%d",&a[i]);
  62. if(!h[a[i]])
  63. {
  64. h[a[i]]=++tot;
  65. s[tot].insert();
  66. s[tot].insert(n+);
  67. }
  68. int tmp=h[a[i]];
  69. s[tmp].insert(i);
  70. pre[i]=*--(s[tmp].insert(i).first);//
  71. }
  72. a[n+]=a[n];//!
  73. build(,,n);
  74. for(int i=,op,x,y,l,r,k;i<=m;i++)
  75. {
  76. scanf("%d",&op);
  77. if(op==)
  78. {
  79. scanf("%d%d",&x,&y);
  80. x^=key; y^=key;
  81. int tmp,nxt,pr;
  82. tmp=h[a[x]];
  83. nxt=*s[tmp].upper_bound(x);
  84. if(nxt!=n+)
  85. {
  86. pre[nxt]=pre[x];
  87. update(,,n,nxt);
  88. }
  89. s[tmp].erase(x);
  90.  
  91. if(!h[y])//
  92. {
  93. h[y]=++tot;
  94. s[tot].insert();
  95. s[tot].insert(n+);
  96. }
  97. tmp=h[y];
  98. s[tmp].insert(x);
  99. nxt=*s[tmp].upper_bound(x);
  100. pre[x]=*--s[tmp].lower_bound(x);
  101. if(nxt!=n+)
  102. {
  103. pre[nxt]=x;
  104. update(,,n,nxt);
  105. }
  106. a[x]=y;
  107. update(,,n,x);
  108. if(x!=)update(,,n,x-);//
  109. }
  110. if(op==)
  111. {
  112. scanf("%d%d%d",&l,&r,&k);
  113. l^=key; r^=key; k^=key;
  114. if(l==r){key++; printf("Yes\n"); continue;}
  115. N tmpp=query(,,n,l,r-);//
  116. N tmp=tmpp+query(,,n,r,r);//
  117. if(k==)
  118. {
  119. if(tmp.mx==tmp.mn)key++,printf("Yes\n");
  120. else printf("No\n");
  121. continue;
  122. }
  123. if(tmp.fro<l && tmp.mx==k*(r-l)+tmp.mn && tmpp.g%k==)//tmpp!
  124. key++,printf("Yes\n");
  125. else printf("No\n");
  126. }
  127. }
  128. return ;
  129. }

bzoj4373 算术天才⑨与等差数列——线段树+set的更多相关文章

  1. [BZOJ4373]算术天才⑨与等差数列(线段树)

    [l,r]中所有数排序后能构成公差为k的等差数列,当且仅当: 1.区间中最大数-最小数=k*(r-l) 2.k能整除区间中任意两个相邻数之差,即k | gcd(a[l+1]-a[l],a[l+2]-a ...

  2. BZOJ4373: 算术天才⑨与等差数列(线段树 hash?)

    题意 题目链接 Sol 正经做法不会,听lxl讲了一种很神奇的方法 我们考虑如果满足条件,那么需要具备什么条件 设mx为询问区间最大值,mn为询问区间最小值 mx - mn = (r - l) * k ...

  3. 【BZOJ4373】算术天才⑨与等差数列 线段树+set

    [BZOJ4373]算术天才⑨与等差数列 Description 算术天才⑨非常喜欢和等差数列玩耍.有一天,他给了你一个长度为n的序列,其中第i个数为a[i].他想考考你,每次他会给出询问l,r,k, ...

  4. 【BZOJ4373】算术天才⑨与等差数列 [线段树]

    算术天才⑨与等差数列 Time Limit: 10 Sec  Memory Limit: 128 MB[Submit][Status][Discuss] Description 算术天才⑨非常喜欢和等 ...

  5. BZOJ 4373 算术天才⑨与等差数列 线段树+set(恶心死我了)

    mdzz,这道题重构了4遍,花了一个晚上... 满足等差数列的条件: 1. 假设min是区间最小值,max是区间最大值,那么 max-min+k(r−l) 2. 区间相邻两个数之差的绝对值的gcd=k ...

  6. BZOJ 4373算术天才⑨与等差数列(线段树)

    题意:给你一个长度为n的序列,有m个操作,写一个程序支持以下两个操作: 1. 修改一个值 2. 给出三个数l,r,k, 询问:如果把区间[l,r]的数从小到大排序,能否形成公差为k的等差数列. n,m ...

  7. BZOJ 4373: 算术天才⑨与等差数列 线段树

    Description 算术天才⑨非常喜欢和等差数列玩耍. 有一天,他给了你一个长度为n的序列,其中第i个数为a[i]. 他想考考你,每次他会给出询问l,r,k,问区间[l,r]内的数从小到大排序后能 ...

  8. bzoj 4373 算术天才⑨与等差数列——线段树+set

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4373 能形成公差为k的等差数列的条件:mx-mn=k*(r-l) && 差分 ...

  9. BZOJ4373 算术天才⑨与等差数列 【线段树】*

    BZOJ4373 算术天才⑨与等差数列 Description 算术天才⑨非常喜欢和等差数列玩耍. 有一天,他给了你一个长度为n的序列,其中第i个数为a[i]. 他想考考你,每次他会给出询问l,r,k ...

随机推荐

  1. [Windows Server 2012] 服务器安全加固

    ★ 欢迎来到[护卫神·V课堂],网站地址:http://v.huweishen.com★ 护卫神·V课堂 是护卫神旗下专业提供服务器教学视频的网站,每周更新视频.★ 本节我们将带领大家:服务器安全加固 ...

  2. 【VHDL】深度讲解二进制无符号和有符号加法处理溢出的问题

    1.Unsigned adders 这个比较简单,只需在A.B前面扩展一位0防止溢出,溢出的数填到第n位cout,n-1到0位就是sum. , 2.Signed adders 一开始也搞不懂下图中为什 ...

  3. python os os.path模块学习笔记

    #!/usr/bin/env python #coding=utf-8 import os #创建目录 os.mkdir(r'C:\Users\Silence\Desktop\python') #删除 ...

  4. PHP采用301跳转方式防CC拦截

    PHP采用301跳转方式防CC拦截   降低CC攻击的效果 <?php empty($_SERVER['HTTP_VIA']) or exit('Access Denied'); $second ...

  5. js 简单小知识

    1. javascript的typeof返回哪些数据类型: string, boolean, number, undefined, function, object 2. split() join() ...

  6. Cat VS Dog HDU_3829(最大独立集最大匹配)

    Cat VS Dog 题意:一群小朋友去动物园,如果每个小朋友喜欢的动物是猫,那么不喜欢的动物一定是狗,反之也是.现在动物园的管理者要拿走一些动物,如果拿走的是某个小朋友不喜欢的动物,那这个小朋友就非 ...

  7. vue项目中的常见问题(vue-cli版本3.0.0)

    一.样式问题 1.vue中使用less 安装less依赖 npm install less less-loader --save-dev 在使用时 在style标签中加入 lang="les ...

  8. navicate远程访问ubuntu上的mysql数据库

    安装mysql 首先检查系统中是否已经安装了MySQL,在终端里面输入: sudo netstat -tap | grep mysql 如上所示就是正确安装并启动,启动命令为 sudo /etc/in ...

  9. Lucas小记

    组合数学全忘了 记笔记记笔记 做个简单题 代码 from bzoj4403 #include <stdio.h> #define p 1000003 typedef long long l ...

  10. Leetcode 39.组合总数

    组合总数 给定一个无重复元素的数组 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合. candidates 中的数字可以无限 ...