题目链接 GukiZ and GukiZiana

题目大意:一个数列,支持两个操作。一种是对区间$[l, r]$中的数全部加上$k$,另一种是查询数列中值为$x$的下标的最大值减最小值。

$n <= 500000, q <= 50000$

我一开始的反应是线段树,然后发现自己完全想错了……

这道题时限$10$秒,但也很容易超时。我后来是用分块过的。

把序列分成$\sqrt{n}$个块,每个块的大小为$\sqrt{n}$(最后一个块可能因为不能整除的关系可能会小一些)

每个块维护一个值$delta[i]$,表示这块的每一个数值都要加上这个值。

第1种操作的时候,找到$l$和$r$所在的块。

这两个块之间(不包含$l$所在的块和$r$所在的块,如果没有就不修改)的所有块的$delta$都加上$x$

这样就降低了修改的时间复杂度

$l$所在的块中的元素依次遍历,若下标满足$l <= i <= r$,则值加$x$

$r$所在的块中的元素依次遍历,若下标满足$l <= i <= r$,则值加$x$

每个块内按照值升序排序(第二关键字为下标)

当一个块的整体大小顺序可能发生改变时,就对这个块内部$sort$一遍,当然没必要$sort$的时候不要$sort$

不然可能$TLE$

查询的时候对每个块二分查找,找到值为$x$的元素的下标,并实时更新答案。

时间复杂度$O(q\sqrt{n}log(\sqrt{n}))$

#include <bits/stdc++.h>

using namespace std;

#define rep(i, a, b)	for (int i(a); i <= (b); ++i)
#define dec(i, a, b) for (int i(a); i >= (b); --i)
#define fi first
#define se second typedef long long LL; const int N = 500010;
const int Q = 810; int block_size, block_num, n, q, c[N], cnt, et, op, l, r;
LL a[N], delta[N], x;
vector <pair<LL, int> > block[Q]; void update(int l, int r, LL x){ rep(i, c[l] + 1, c[r] - 1)
delta[i] += x; for (auto &node : block[c[l]])
if (node.se >= l && node.se <= r)
node.fi += x; sort(block[c[l]].begin(), block[c[l]].end()); if (c[r] > c[l]){
for (auto &node : block[c[r]])
if (node.se >= l && node.se <= r)
node.fi += x; sort(block[c[r]].begin(), block[c[r]].end()); } } void query(LL x){
int L = 1 << 30, R = -1;
rep(i, 1, block_num){
auto it = lower_bound(block[i].begin(), block[i].end(), make_pair(x - delta[i], 0));
if (it != block[i].end() && it -> first == x - delta[i])
L = min(L, it -> se); it = lower_bound(block[i].begin(), block[i].end(), make_pair(x - delta[i] + 1, 0));
if (it != block[i].begin()){
--it;
if (it -> fi == x - delta[i])
R = max(R, it -> se);
}
} if (~R) printf("%d\n", R - L);
else puts("-1");
} int main(){ scanf("%d%d", &n, &q);
rep(i, 1, n) scanf("%lld", a + i);
block_size = sqrt(n + 0.5); block_num = n / block_size;
if (n % block_size) ++block_num; cnt = 1;
rep(i, 1, n){
++et;
c[i] = cnt;
block[cnt].push_back({a[i], i});
if (et == block_size){
et = 0;
++cnt;
} } rep(i, 1, block_num) sort(block[i].begin(), block[i].end()); for (; q--; ){
scanf("%d", &op);
if (op == 1){
scanf("%d%d%lld", &l, &r, &x);
update(l, r, x);
} else{
scanf("%lld", &x);
query(x);
}
} return 0;
}

Codeforces 551E GukiZ and GukiZiana(分块思想)的更多相关文章

  1. Codeforces 551E - GukiZ and GukiZiana(分块)

    Problem E. GukiZ and GukiZiana Solution: 先分成N=sqrt(n)块,然后对这N块进行排序. 利用二分查找确定最前面和最后面的位置. #include < ...

  2. CodeForces 551E GukiZ and GukiZiana

    GukiZ and GukiZiana Time Limit: 10000ms Memory Limit: 262144KB This problem will be judged on CodeFo ...

  3. CF 551E. GukiZ and GukiZiana [分块 二分]

    GukiZ and GukiZiana 题意: 区间加 给出$y$查询$a_i=a_j=y$的$j-i$最大值 一开始以为和论文CC题一样...然后发现他带修改并且是给定了值 这样就更简单了.... ...

  4. Codeforces Round #307 (Div. 2) E. GukiZ and GukiZiana 分块

    E. GukiZ and GukiZiana Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/contest/55 ...

  5. Codeforces 307 div2 E.GukiZ and GukiZiana 分块

    time limit per test 10 seconds memory limit per test 256 megabytes input standard input output stand ...

  6. Codeforces Round #307 (Div. 2) E. GukiZ and GukiZiana(分块)

    E. GukiZ and GukiZiana time limit per test 10 seconds memory limit per test 256 megabytes input stan ...

  7. Codeforces 551 E - GukiZ and GukiZiana

    E - GukiZ and GukiZiana 思路:分块, 块内二分 代码: #pragma GCC optimize(2) #pragma GCC optimize(3) #pragma GCC ...

  8. Codeforces Round #319 (Div. 1)C. Points on Plane 分块思想

                                                                              C. Points on Plane On a pl ...

  9. [codeforces551E]GukiZ and GukiZiana

    [codeforces551E]GukiZ and GukiZiana 试题描述 Professor GukiZ was playing with arrays again and accidenta ...

随机推荐

  1. Linux下的jdk安装

    我使用的是CentOS7,jdk使用的是JDK1.8 下载好以后,将jdk传到我自己的目录:/home/tool下,通过 tar -xzvf  jdk-8u131-linux-x64.tar.gz解压 ...

  2. solr配置中文分词器

    配置IK分词器 在/opt/solr-7.7.1/server/solr-webapp/webapp/WEB-INF/lib目录中加入IK分词器的jar包 在/opt/solr-7.7.1/serve ...

  3. HDU - 4027 Can you answer these queries?(线段树)

    给定一个长度为n的序列,m次操作. 每次操作 可以将一个区间内的所有数字变为它的根号. 可以查询一个区间内所有元素的和. 线段树的初级应用. 如果把一个区间内的元素都改为它的根号的话,是需要每个数字都 ...

  4. SQL_4_函数

    在SQL的函数中可以执行一些诸如对某一些进行汇总或将一个字符串中的字符转换为大写的操作等: 函数有:汇总函数.日期与时间函数.数学函数.字符函数.转换函数与其他函数. 汇总函数 这是一组函数,它们返回 ...

  5. html-body相关标签

    一 字体标签   字体标签包含:h1~h6.<font>.<u>.<b>.<strong><em>.<sup>.<sub& ...

  6. 精通 JavaScript中的正则表达式

    精通 JS正则表达式 (精通?标题党 ) 正则表达式可以: •测试字符串的某个模式.例如,可以对一个输入字符串进行测试,看在该字符串是否存在一个电话号码模式或一个信用卡号码模式.这称为数据有效性验证  ...

  7. python-高级编程-05-异步IO

    [异步非阻塞IO] ------------------------------------------------------------------------------------------ ...

  8. LaTeX新人教程,30分钟从完全陌生到基本入门[转载]

    LaTeX新人教程,30分钟从完全陌生到基本入门[转载] 2017-02-05 分类:TeX讲义 阅读(32514) 评论(0)  这是一篇老文了,前几天看微博的时候看到的,文中的很多表达比较过激,思 ...

  9. 【Luogu】P3317重建(高斯消元+矩阵树定理)

    题目链接 因为这个专门跑去学了矩阵树定理和高斯消元qwq 不过不是很懂.所以这里只放题解 玫葵之蝶的题解 某未知dalao的矩阵树定理 代码 #include<cstdio> #inclu ...

  10. SiteMapPath控件的使用(ASP.NET)

    最近在博客里写了一些日志,主要都是我在实际编程过程中遇到的问题.问题出现后,先自己推敲,搞不定的,就上网去搜,再就是请教同学.同事,从中获益匪浅,也很难得!现在把感觉比较实用的一些功能代码之类的发布到 ...