您的位置:首页 > 其它

codeforces 551E GukiZ and GukiZiana 分块

2017-10-09 17:28 337 查看

题目:

https://vjudge.net/problem/CodeForces-551E

题意:

给定一个长度为n的序列a,有两种操作:

1 l r x:把区间[l,r]内的元素都加上x

2 y:查询整个序列中值为y的元素的最远距离,若没有y输出−1

思路:

分块,注意爆int

#include <bits/stdc++.h>
using namespace std;

typedef long long ll;
const int N = 500000 + 10, INF = 0x3f3f3f3f;

int L
, R
, pos
;
int sz, block;

ll a
, b
, add
;
void reset(int x)
{
for(int i = L[x]; i <= R[x]; i++) b[i] = a[i];
sort(b + L[x], b + 1 + R[x]);
}
void init(int n)
{
block = (int)sqrt(n);
sz = n / block;
if(n % block) sz++;
for(int i = 1; i <= n; i++) pos[i] = (i-1) / block + 1;
for(int i = 1; i <= sz; i++)
{
L[i] = (i-1) * block + 1;
R[i] = i * block;
}
R[sz] = n;
for(int i = 1; i <= sz; i++) reset(i);
memset(add, 0, sizeof add);
}
void update(int l, int r, int val)
{
int lb = pos[l], rb = pos[r];
if(lb == rb)
{
for(int i = l; i <= r; i++) a[i] += val;
reset(lb);
}
else
{
for(int i = l; i <= R[lb]; i++) a[i] += val;
for(int i = L[rb]; i <= r; i++) a[i] += val;
for(int i = lb+1; i < rb; i++) add[i] += val;
reset(lb); reset(rb);
}
}
int query(ll val)
{
int x = 0, y = 0;
for(int i = 1; i <= sz; i++)
if(binary_search(b + L[i], b + 1 + R[i], val - add[i]))
{
for(int j = L[i]; j <= R[i]; j++)
if(a[j] + add[i] == val)
{
x = j; break;
}
break;
}
for(int i = sz; i >= 1; i--)
if(binary_search(b + L[i], b + 1 + R[i], val - add[i]))
{
for(int j = R[i]; j >= L[i]; j--)
if(a[j] + add[i] == val)
{
y = j; break;
}
break;
}
if(!x && !y) return -1;
else return y - x;
}
int main()
{
int n, m;
while(~ scanf("%d%d", &n, &m))
{
for(int i = 1; i <= n; i++) scanf("%lld", &a[i]);
init(n);
int opt, x, y, z;
for(int i = 1; i <= m; i++)
{
scanf("%d", &opt);
if(opt == 1)
{
scanf("%d%d%d", &x, &y, &z);
update(x, y, z);
}
else
{
scanf("%d", &x);
printf("%d\n", query(x));
}
}
}

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: