[CF551E]GukiZ and GukiZiana
题目大意:一个长度为$n(n\leqslant5\times10^5)$的数组,有两个操作:
- $1\;l\;r\;x:$把区间$[l,r]$加上$x$
- $2\;x:$询问$x$第一次出现和最后一次出现之间的距离,若没出现输出$-1$
题解:分块,把每个块排个序(可以把数值为第一关键字,位置为第二关键字),整块的加就块上打$tag$,非整块的就暴力重构,查询就在每个块内求这个数出现位置,直接二分查找就行了。设块大小为$S$,修改复杂度$O(\dfrac n S+2S)$,查询复杂度$O(\dfrac n S\log_2 S)$,$S$略大于$\sqrt n$最好。
卡点:无
C++ Code:
#include <algorithm>
#include <cstdio>
#include <cctype>
namespace IO {
struct istream {
#define M (1 << 24 | 3)
char buf[M], *ch = buf - 1;
inline istream() {
#ifndef ONLINE_JUDGE
freopen("input.txt", "r", stdin);
#endif
fread(buf, 1, M, stdin);
}
inline istream& operator >> (int &x) {
while (isspace(*++ch));
for (x = *ch & 15; isdigit(*++ch); ) x = x * 10 + (*ch & 15);
return *this;
}
inline istream& operator >> (long long &x) {
while (isspace(*++ch));
for (x = *ch & 15; isdigit(*++ch); ) x = x * 10 + (*ch & 15);
return *this;
}
#undef M
} cin;
struct ostream {
#define M (1 << 24 | 3)
char buf[M], *ch = buf - 1;
int w;
inline ostream& operator << (int x) {
if (!x) {
*++ch = '0';
return *this;
}
if (x < 0) *++ch = '-', x = -x;
for (w = 1; w <= x; w *= 10);
for (w /= 10; w; w /= 10) *++ch = (x / w) ^ 48, x %= w;
return *this;
}
inline ostream& operator << (const char x) {*++ch = x; return *this;}
inline ~ostream() {
#ifndef ONLINE_JUDGE
freopen("output.txt", "w", stdout);
#endif
fwrite(buf, 1, ch - buf + 1, stdout);
}
#undef M
} cout;
} #define maxn 500010
const int BSZ = 1 << 10, BNUM = maxn / BSZ + 10; int bel[maxn];
int L[BNUM], R[BNUM];
long long tg[BNUM];
struct node {
long long s;
int id;
inline node() {}
inline node(long long __s, int __id) : s(__s), id(__id) {}
inline node(int __s, int __id) {s = __s, id = __id;}
inline friend bool operator < (const node &lhs, const node &rhs) {
return lhs.s == rhs.s ? lhs.id < rhs.id : lhs.s < rhs.s;
}
} s[maxn]; int n, m, Bnum; int query(const int x) {
int max = 0, min = 0;
for (int i = 1; i <= Bnum; i++) if (tg[i] <= x) {
const int y = x - tg[i];
int l = std::lower_bound(s + L[i], s + R[i], node(y, 0)) - s;
if (l != R[i] && s[l].s == y) {
int r = std::lower_bound(s + L[i], s + R[i], node(y + 1, 0)) - s - 1;
if (!min) min = s[l].id;
max = s[r].id;
}
}
if (!min) return -1;
return max - min;
}
int main() {
IO::cin >> n >> m;
for (int i = 1; i <= n; i++) {
IO::cin >> s[i].s; s[i].id = i;
bel[i] = (i - 1 >> 10) + 1;
} Bnum = bel[n];
for (int i = 1; i <= Bnum; i++) {
L[i] = i - 1 << 10, R[i] = L[i] + BSZ;
}
L[1] = 1, R[Bnum] = n + 1;
for (int i = 1; i <= Bnum; i++) {
std::sort(s + L[i], s + R[i]);
} while (m --> 0) {
int op, l, r, x;
IO::cin >> op >> l;
if (op == 1) {
IO::cin >> r >> x;
const int lb = bel[l], rb = bel[r];
if (lb == rb) {
for (register node *now = s + L[lb]; now != s + R[lb]; ++now) if (l <= now -> id && now -> id <= r) now -> s += x;
std::sort(s + L[lb], s + R[lb]);
} else {
for (register node *now = s + L[lb]; now != s + R[lb]; ++now) if (l <= now -> id) now -> s += x;
std::sort(s + L[lb], s + R[lb]);
for (int i = lb + 1; i < rb; i++) tg[i] += x;
for (register node *now = s + L[rb]; now != s + R[rb]; ++now) if (now -> id <= r) now -> s += x;
std::sort(s + L[rb], s + R[rb]);
}
} else {
IO::cout << query(l) << '\n';
}
}
return 0;
}
[CF551E]GukiZ and GukiZiana的更多相关文章
- 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 ...
- Codeforces 551E - GukiZ and GukiZiana(分块)
Problem E. GukiZ and GukiZiana Solution: 先分成N=sqrt(n)块,然后对这N块进行排序. 利用二分查找确定最前面和最后面的位置. #include < ...
- CF 551E. GukiZ and GukiZiana [分块 二分]
GukiZ and GukiZiana 题意: 区间加 给出$y$查询$a_i=a_j=y$的$j-i$最大值 一开始以为和论文CC题一样...然后发现他带修改并且是给定了值 这样就更简单了.... ...
- Codeforces 551 E - GukiZ and GukiZiana
E - GukiZ and GukiZiana 思路:分块, 块内二分 代码: #pragma GCC optimize(2) #pragma GCC optimize(3) #pragma GCC ...
- 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 ...
- Codeforces 551E GukiZ and GukiZiana(分块思想)
题目链接 GukiZ and GukiZiana 题目大意:一个数列,支持两个操作.一种是对区间$[l, r]$中的数全部加上$k$,另一种是查询数列中值为$x$的下标的最大值减最小值. $n < ...
- [codeforces551E]GukiZ and GukiZiana
[codeforces551E]GukiZ and GukiZiana 试题描述 Professor GukiZ was playing with arrays again and accidenta ...
- CodeForces 551E GukiZ and GukiZiana
GukiZ and GukiZiana Time Limit: 10000ms Memory Limit: 262144KB This problem will be judged on CodeFo ...
- Codeforces 307 div2 E.GukiZ and GukiZiana 分块
time limit per test 10 seconds memory limit per test 256 megabytes input standard input output stand ...
随机推荐
- Rails导出CSV
版本 ruby 1.9 rails 3.2 完整代码 #引入CSV标准类库 require 'csv' class PeopleController < ApplicationControl ...
- 「Python」Convert map object to numpy array in python 3
转自Stackoverflow.备忘用. Question In Python 2 I could do the following: import numpy as np f = lambda x: ...
- Python 更换国内pip源
pip国内的一些镜像: 阿里云 http://mirrors.aliyun.com/pypi/simple/ 中国科技大学 https://pypi.mirrors.ustc.edu.cn/sim ...
- Appium的一点一滴:Android KEYCODE键值
转自:http://blog.csdn.net/crisschan/article/details/50419963 - 电话键 键名 描述 键值 KEYCODE_CALL 拨号键 5 KEYCODE ...
- egrep及扩展正则
模式:pattern 正则: grep:基本正则,查找速度慢 Extended grep:扩展正则 fgrep:fast grep,不支持正则,直接查找字符串,执行速度快 基本正则: . :任意单个字 ...
- 用Python实现一个端口扫描,只需简单几步就好
一.常见端口扫描的原理 0.秘密扫描 秘密扫描是一种不被审计工具所检测的扫描技术. 它通常用于在通过普通的防火墙或路由器的筛选(filtering)时隐藏自己. 秘密扫描能躲避IDS.防火墙.包过滤器 ...
- 100. Remove Duplicates from Sorted Array && 101. Remove Duplicates from Sorted Array II [easy]
这两题类似,所以放在一起,先看第一题: Description Given a sorted array, remove the duplicates in place such that each ...
- 【转】从零开始学习Skynet_examples研究
转自 http://blog.csdn.net/mr_virus/article/details/52330193 一.编译Skynet: 1.用ubuntu15.10直接 make linux 编译 ...
- chrome编辑器与截图
在地址栏中输入 data:text/html,<html contenteditable>即可使用编辑功能,打开控制台,ctrl + shift + p 调用命令面板,输入 capture ...
- 使用深度学习来破解 captcha 验证码(转)
使用深度学习来破解 captcha 验证码 本项目会通过 Keras 搭建一个深度卷积神经网络来识别 captcha 验证码,建议使用显卡来运行该项目. 下面的可视化代码都是在 jupyter not ...