题意:给你5e4个数,1e6个询问(时限10s),两个操作:操作一区间加一个数,操作二,区间询问数y的最大坐标差,区间没有y就输出 -1;
分析:根号分块,预处理排序,块内维护排序,reset函数就是当区间加作用在不完整块的时候,用来重新排序,维护这个块的有序性,最后查询的时候,两次二分,分别二分最小最大位置,输出R- L即可;
不过第一版代码的询问不知道为啥错了,wa32,一直想不明白
PS:今天终于学了分块,感觉数据结构现在才算把大的漏洞补完,个人感觉分块还是很厉害的,毕竟通用面更广;
AC代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e6 + 15;
const int mo = 998244353;
#define pb push_back
#define pii pair<int,int>
#define ft first
#define sd second
#define ffor(i,a,b,c) for(int i=(a);i<(b);i+=(c))
#define For(i,a,b,c) for(int i=(a);i<=(b);i+=(c))
#define rfor(i,a,b,c) for(int i=(a);i>(b);i-=(c))
#define Rfor(i,a,b,c) for(int i=(a);i>=(b);i-=(c))
#define all(x) (x).begin(), (x).end()
#define debug1(x) cerr<<"! "<<x<<endl;
#define debug2(x,y) cerr<<"# "<<x<<" "<<y<<endl;
#define int long long
class Partition
{
public:
Partition(int _n): n(_n) {
bl.resize(n + 1), v.resize(n + 1), tag.resize(n + 1);
ve.resize(n + 1);
blo = sqrt(n);
for (int i = 1; i <= n; i++) {
cin >> v[i];
bl[i] = (i - 1) / blo + 1;
ve[bl[i]].pb({v[i], i});
}
for (int i = 1; i <= (n + blo - 1) / blo; i++) {
sort(ve[i].begin(), ve[i].end());
}
}
void reset(int x) {
ve[bl[x]].clear();
for (int i = (bl[x] - 1) * blo + 1; i <= min(bl[x]*blo, n); i++) {
ve[bl[x]].pb({v[i], i});
}
sort(ve[bl[x]].begin(), ve[bl[x]].end());
}
void add(int l, int r, int c) {
for (int i = l; i <= min(bl[l]*blo, r); i++) {
v[i] += c;
}
reset(l);
if (bl[l] != bl[r]) {
for (int i = (bl[r] - 1) * blo + 1; i <= r; i++) {
v[i] += c;
}
reset(r);
}
for (int i = bl[l] + 1; i <= bl[r] - 1; i++) {
tag[i] += c;
}
}
int query(int y) {
int L = 1e9, R = -1e9;
for (int i = 1; i <= (n + blo - 1) / blo; i++) {
int ll = lower_bound(ve[i].begin(), ve[i].end(), make_pair(1ll*(y - tag[i]), 0ll)) - ve[i].begin();
int rr = lower_bound(ve[i].begin(), ve[i].end(), make_pair(1ll*(y - tag[i] + 1), 0ll)) - ve[i].begin() - 1;
if(ll <= rr) {
L = min(L, ve[i][ll].sd);
R = max(R, ve[i][rr].sd);
}
}
// debug2(L, R);
if (L > R) return -1;
else return R - L;
}
private:
vector<int> bl, v, tag;
vector<vector<pii>> ve;
int blo, n;
};
void slv() {
int n, m; cin >> n >> m;
Partition Pt(n);
for (int i = 1; i <= m; i++) {
int op; cin >> op;
if (op == 1) {
int l, r, x; cin >> l >> r >> x;
Pt.add(l, r, x);
} else {
int y; cin >> y;
cout << Pt.query(y) << '\n';
}
}
}
signed main() {
ios::sync_with_stdio(false); cin.tie(0);
slv();
}