CodeForces 551E 分块
题目链接:http://codeforces.com/problemset/problem/551/E
题意:给定一个长度为N的序列。 有2个操作 1 l r v:序列第l项到第r项加v(区间加), 2 v:求整个序列中值为v的数的位置的差值最大是多少。不存在输出-1.
思路:分块。 每块维护该块序列排序后的序列。 对于区间修改,我们定义一个lazy标记。对于整块的修改我们只修改lazy, 其他情况暴力修改。然后情况该块后重新加入修改后的块然后排序。 对于查询操作。查询每块时v应该减去该块的lazy值。 然后2分查即可。
#define _CRT_SECURE_NO_DEPRECATE #include<stdio.h> #include<string.h> #include<cstring> #include<algorithm> #include<queue> #include<math.h> #include<time.h> #include<vector> #include<iostream> #include<map> using namespace std; typedef long long int LL; const int MAXN = 5*100000 + 10; int belong[MAXN], block, num, L[MAXN], R[MAXN]; int n, q; LL val[MAXN], lazy[MAXN]; struct Node{ LL v; int id; Node(LL _v, int _id) :v(_v), id(_id){}; bool operator < (const Node &a)const{ return v==a.v?id<a.id:v<a.v; } }; vector<Node>Bval[MAXN]; void build(){ block = (int)sqrt(n+0.5); num = n / block; if (n%block){ num++; } for (int i = 1; i <= num; i++){ lazy[i] = 0; Bval[i].clear(); L[i] = (i - 1)*block + 1; R[i] = i*block; } R[num] = n; for (int i = 1; i <= n; i++){ belong[i] = ((i - 1) / block) + 1; } for (int i = 1; i <= num; i++){ for (int k = L[i]; k <= R[i]; k++){ Bval[i].push_back(Node(val[k],k)); } sort(Bval[i].begin(), Bval[i].end()); } } void modify(int st,int ed, LL v){ if (belong[st] == belong[ed]){ for (int i = st; i <= ed; i++){ val[i] += v; } Bval[belong[st]].clear(); for (int i = L[belong[st]]; i <= R[belong[st]]; i++){ Bval[belong[st]].push_back(Node(val[i], i)); } sort(Bval[belong[st]].begin(), Bval[belong[st]].end()); return; } for (int i = st; i <= R[belong[st]]; i++){ val[i] += v; } Bval[belong[st]].clear(); for (int i = L[belong[st]]; i <= R[belong[st]]; i++){ Bval[belong[st]].push_back(Node(val[i], i)); } sort(Bval[belong[st]].begin(), Bval[belong[st]].end()); for (int i = belong[st] + 1; i < belong[ed]; i++){ lazy[i] += v; } for (int i = L[belong[ed]]; i <= ed; i++){ val[i] += v; } Bval[belong[ed]].clear(); for (int i = L[belong[ed]]; i <= R[belong[ed]]; i++){ Bval[belong[ed]].push_back(Node(val[i], i)); } sort(Bval[belong[ed]].begin(), Bval[belong[ed]].end()); } int query(LL v){ int L = -1, R = -1; for (int i = 1; i <= num; i++){ LL _v = v-lazy[i]; int pos = lower_bound(Bval[i].begin(), Bval[i].end(), Node(_v,0)) - Bval[i].begin(); if (pos >= 0 && pos < Bval[i].size() && Bval[i][pos].v == _v){ L = Bval[i][pos].id; break; } } if (L == -1){ return -1; } for (int i = num; i > 0; i--){ LL _v = v - lazy[i]; int pos = (lower_bound(Bval[i].begin(), Bval[i].end(), Node( _v + 1,0)) - Bval[i].begin())-1; if (pos >= 0 && pos < Bval[i].size() && Bval[i][pos].v == _v){ R = Bval[i][pos].id; break; } } return R - L; } int main(){ //#ifdef kirito // freopen("in.txt", "r", stdin); // freopen("out.txt", "w", stdout); //#endif // int start = clock(); while (~scanf("%d%d", &n,&q)){ for (int i = 1; i <= n; i++){ scanf("%lld", &val[i]); } build(); for (int i = 1; i <= q; i++){ int type, l, r, v; scanf("%d", &type); if (type == 1){ scanf("%d%d%lld", &l, &r, &v); modify(l, r, v); } else{ scanf("%lld", &v); printf("%d\n", query(v)); } } } //#ifdef LOCAL_TIME // cout << "[Finished in " << clock() - start << " ms]" << endl; //#endif return 0; }