Codeforces 307 div2 E.GukiZ and GukiZiana 分块
10 seconds
256 megabytes
standard input
standard output
Professor GukiZ was playing with arrays again and accidentally discovered new function, which he called GukiZiana. For given array a, indexed with integers from 1 to n, and number y, GukiZiana(a, y) represents maximum value of j - i, such that aj = ai = y. If there is no y as an element in a, then GukiZiana(a, y) is equal to - 1. GukiZ also prepared a problem for you. This time, you have two types of queries:
- First type has form 1 l r x and asks you to increase values of all ai such that l ≤ i ≤ r by the non-negative integer x.
- Second type has form 2 y and asks you to find value of GukiZiana(a, y).
For each query of type 2, print the answer and make GukiZ happy!
The first line contains two integers n, q (1 ≤ n ≤ 5 * 105, 1 ≤ q ≤ 5 * 104), size of array a, and the number of queries.
The second line contains n integers a1, a2, ... an (1 ≤ ai ≤ 109), forming an array a.
Each of next q lines contain either four or two numbers, as described in statement:
If line starts with 1, then the query looks like 1 l r x (1 ≤ l ≤ r ≤ n, 0 ≤ x ≤ 109), first type query.
If line starts with 2, then th query looks like 2 y (1 ≤ y ≤ 109), second type query.
For each query of type 2, print the value of GukiZiana(a, y), for y value for that query.
4 3
1 2 3 4
1 1 2 1
1 1 1 1
2 3
2
2 3
1 2
1 2 2 1
2 3
2 4
0
-1 题意:给你一个n个数的序列,以及q个操作,有两种操作,1是区间[l,r]上的每个数加上v 2是查询y,求aj = ai = y的最大j-i
思路:我想到分块的做法,分为tb块,每一块中的每个元素保存v和id,然后每一块按v排序,相等按id排序,这样对于查询的时候,我们只需要从左到右找到第一块满足存在y,那么pl = lowwer_bound(y)。同理从右到左找到第一块满足存在y,那么pr = upper_bound(y)。 答案就是pr-pl。
对于更新操作,区间[l,r]所覆盖的块中,第一块和最后一块暴力更新,并且重建块,即重新排序。而对于中间的完整覆盖的块,我们只记录增量add[b],因为add[b]表示b整块的增量,那么b快依然有序,在b块查询x的时候,x -= add[b]即可。 做法很快想好了,但wa了好多发,就是以为不会爆ll。。。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 5e5 + ;
const int SIZE = ;
struct Block {
ll v; int id;
Block() {}
Block(ll v, int id) : v(v), id(id) {}
friend bool operator < (Block a, Block b) {
if(a.v == b.v) return a.id < b.id;
return a.v < b.v;
};
};
Block block[N/SIZE + ][SIZE + ];
int n, q;
ll A[N];
ll add[N/SIZE + ];
int tb, ls; void init() {
scanf("%d%d", &n, &q);
int b = , j = ;
for(int i = ; i < n; ++i) {
scanf("%I64d", &A[i]);
block[b][j] = Block(A[i], i);
if(++j == SIZE) { b++; j = ;}
}
ls = ;
for(int i = ; i < b; ++i) sort(block[i], block[i] + SIZE);
if(j) { ls = j; sort(block[b], block[b] + j); }
tb = b;
}
void rebuild(int b, int sz) {
int j = ;
for(int i = b * SIZE; i < b * SIZE + sz; ++i) block[b][j++] = Block(A[i], i);
sort(block[b], block[b] + j);
}
void update(int L, int R, int v) {
int lb = L / SIZE, rb = R / SIZE, j, sz;
if(lb == rb) {
for(int i = L; i <= R; ++i) A[i] += v;
if(lb == tb) sz = ls;
else sz = SIZE;
rebuild(lb, sz);
}else {
for(int i = L; i < (lb + ) * SIZE; ++i) A[i] += v;
rebuild(lb, SIZE); for(int i = rb * SIZE; i <= R; ++i) A[i] += v;
if(rb == tb) sz = ls;
else sz = SIZE;
rebuild(rb, sz);
for(int b = lb + ; b < rb; ++b) add[b] += v;
}
}
int upper(Block a[], int sz, ll v) {
int L = , R = sz;
while(R - L > ) {
int M = (L + R) >> ;
if(a[M].v <= v) L = M;
else R = M;
}
return L;
}
int lower(Block a[], int sz, ll v) {
int L = , R = sz;
while(L < R) {
int M = (L + R) >> ;
if(a[M].v >= v) R = M;
else L = M + ;
}
return L;
}
int query(ll x) {
int pl = -, pr = -;
ll v;
if(tb == ) {
for(int i = ; i < ls; ++i) if(A[i] == x) { pl = i; break; }
for(int i = ls - ; i >= ; --i) if(A[i] == x) { pr = i; break; }
if(pl == -) return -;
}else {
if(ls) for(int i = tb * SIZE + ls - ; i >= tb * SIZE; --i) if(A[i] == x) { pr = i; break; }
if(pr == -) {
for(int b = tb - ; b >= ; --b) {
v = x - add[b];
int px = upper(block[b], SIZE, v);
if(px < SIZE && block[b][px].v == v) { pr = block[b][px].id; break; }
}
}
if(pr == -) return -;
for(int b = ; b < tb; ++b) {
v = x - add[b];
int pi = lower(block[b], SIZE, v);
if(pi < SIZE && block[b][pi].v == v) { pl = block[b][pi].id; break; }
}
if(pl == -) {
for(int i = tb * SIZE; i < tb * SIZE + ls; ++i) if(A[i] == x) { pl = i; break; }
}
}
return pr - pl;
}
int main() {
//freopen("in.txt", "r", stdin);
init();
int op, l, r, x;
memset(add, , sizeof add);
for(int i = ; i < q; ++i) {
scanf("%d", &op);
if(op == ) {
scanf("%d%d%d", &l, &r, &x);
l--; r--;
update(l, r, x);
}else {
scanf("%d", &x);
printf("%d\n", query(x));
}
}
return ;
}
Codeforces 307 div2 E.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 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 < ...
- CodeForces 551E GukiZ and GukiZiana
GukiZ and GukiZiana Time Limit: 10000ms Memory Limit: 262144KB This problem will be judged on CodeFo ...
- Codeforces 551 E - GukiZ and GukiZiana
E - GukiZ and GukiZiana 思路:分块, 块内二分 代码: #pragma GCC optimize(2) #pragma GCC optimize(3) #pragma GCC ...
- [codeforces551E]GukiZ and GukiZiana
[codeforces551E]GukiZ and GukiZiana 试题描述 Professor GukiZ was playing with arrays again and accidenta ...
- Codeforces #180 div2 C Parity Game
// Codeforces #180 div2 C Parity Game // // 这个问题的意思被摄物体没有解释 // // 这个主题是如此的狠一点(对我来说,),不多说了这 // // 解决问 ...
随机推荐
- linux 命令行 光标移动技巧
linux 命令行 光标移动技巧 看一个真正的专家操作命令行绝对是一种很好的体验-光标在单词之间来回穿梭,命令行不同的滚动.在这里强烈建立适应GUI节目的开发者尝试一下在提示符下面工作.但是事情也不是 ...
- [Unity3D]引擎学习之注意事项(持续更新中)
调试相关 如果是想在触发粒子系统效果的时候播放声音(比如爆炸的特殊发生时也播放声音),则需要将爆炸效果的粒子系统保持为Prefab后,添加Audio Source组件,在组件中添加声音文件并且确保pl ...
- 基于canvas的陈列订货的分析
订货会软件中又新增了进行陈列订货,即一杆衣服订的显示出来,没订的不显示出来 主要遇到的问题是如何呈现,原先老是想着定位,left,top但是花出来的图容易出现原先的数据填写错误导致后期的图片的呈现出现 ...
- javascript面向对象:继承、多态
继承 js中同样可以实现类的继承这一面向对象特性,继承父类中的所有成员(变量和属性),同时可扩展自己的成员,下面介绍几种js中实现继承的方式: 1,对象模仿:通过动态的改变 this 指针的指向,实现 ...
- CSS3中的变形处理
在css3中,可以利用transform功能来实现文字或者图像的旋转.缩放.倾斜.移动这四种类型的变形处理. 旋转 旋转功能使用rotate方法参数中加入角度值,方向为顺时针旋转.示例清单如下: &l ...
- C++项目中的extern "C" {}
from:http://www.cnblogs.com/skynet/archive/2010/07/10/1774964.html C++项目中的extern "C" {} 20 ...
- 深入理解使用ListView时ArrayAdapter、SimpleAdapter、BaseAdapter的原理
在使用ListView的时候,我们传给setAdapter方法的Adapter通常是ArrayAdapter.SimpleAdapter.BaseAdapter,但是这几个Adapter内部究竟是什么 ...
- css中为了清除浮动经常用到的after样式
.cf:after { display: block; visibility: hidden; width:; height:; line-height:; font-size:; clear: bo ...
- Qml 写的弹出层控件
QML弹出窗口组件,灯箱效果.动画效果,可拖拽 核心思路:一个mask层,一个最顶层,都用rectangle,禁止事件穿透 使用 Popup { id: popup width: 200; heigh ...
- Linux下用于查看系统当前登录用户信息 w命令
作为系统管理员,你可能经常会(在某个时候)需要查看系统中有哪些用户正在活动.有些时候,你甚至需要知道他(她)们正在做什么.本文为我们总结了4种查看系统用户信息(通过编号(ID))的方法. 1. 使用w ...