[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 ...
随机推荐
- vim 安装
Ubuntu 16.04 下 Vim安装及配置 默认已经安装了VIM-tiny linuxidc@linuxidc:~$ locate vi | grep 'vi$' |xargs ls -al lr ...
- shell 批量压缩指定目录及子目录内图片的方法
用户上传的图片,一般都没有经过压缩,造成空间浪费.因此需要编写一个程序,查找目录及子目录的图片文件(jpg,gif,png),将大于某值的图片进行压缩处理. 查看目录文件大小 du -h --max- ...
- C#调用大漠插件,发送QQ和微信消息
大漠插件就不过多介绍了,不知道的请查下百度.主要是讲解C#怎么调用大漠插件. 大漠插件提供了COM版本,C#直接点击引用,添加即可.然后注册下大漠插件到系统文件夹,注册代码如下: static str ...
- VIN码识别:让VIN码采集so easy!
近几年汽车后市场呈喷井式发展,在过去的半年,汽车后市场规模已高达万亿级,产业前景广阔,与此同时行业运营也受信息区域化.数据不统一的制约,让企业面临着效率低下.规模化运行困难的痛点. 在汽车配件市场中, ...
- Oracle启动与关闭数据库实例
Oracle数据库启动实例分为3个步骤: 启动实例 加载数据库 打开数据库 通用模式: STARTUP [ nomount | mount | open | force ] [resetrict] ...
- JavaScript --经典问题
JavaScript中如何检测一个变量是一个String类型?请写出函数实现 方法1. function isString(obj){ return typeof(obj) === "str ...
- 2>&1和&>的区别
简单记录下: COMMAND > /path/file 2>&1 COMMAND &> /path/file 这两个效果都是一样的,都是把正确的输入.错误输入存放到同 ...
- leetcode-峰值检测
寻找峰值 峰值元素是指其值大于左右相邻值的元素. 给定一个输入数组 nums,其中 nums[i] ≠ nums[i+1],找到峰值元素并返回其索引. 数组可能包含多个峰值,在这种情况下,返回 ...
- CentOS Openvpn搭建以及 linux&&windows客户端的连接
本文参考:http://www.centoscn.com/CentosServer/test/2014/1120/4153.html 一. Server安装准备 (CentOS release ...
- 自测之Lesson6:文件I/O
题目:区分文件I/O和标准I/O. 区别: ①首先两者一个显著的不同点在于,标准I/O默认采用了缓冲机制,比如调用fopen函数,不仅打开一个文件,而且建立了一个缓冲区(读写模式下将建立两个缓冲区), ...