题目链接
题意:给定一个序列,有两种操作
操作1、区间加权
操作2、询问序列中 a[i] == y 的数的最远距离
即:
for(int i = 0; i < n; i++)if(a[i] == y) L = i, break;
for(int i = n-1; i >= 0; i--)if(a[i]==y)R=i, break;
put(R-L);
思路:分块。
把区间分成 x 块,那么每块长度都为 n/x (如果n/x不能整除则最后一块长度是 n%x)
设 y 为区间长度,即y=n/x;
我们保证每一块的区间都是有序的,即所有修改后都要排个序。
再对每块区间设置一个整体偏移量 long long b;
查询与[l,r]相交的所有块:
if( 这一块被[l,r]完整覆盖 )
b+=val;
else
{
暴力修改:
暴力枚举这块中的所有元素,若这个元素属于[l,r] 则 这个元素+=val
对这块排个序
(显然只有边界的2块是不会被完整覆盖的)
}
查询每一块,因为块是有序的,所以二分一下就好了。
对于操作1:
最多查询块的数量是 x, 暴力修改的复杂度是 O( y*log(y) )
所以操作1的复杂度是 O(x + y*log(y))
对于操作2:
查询块的数量是 x, 查找块内元素是二分 : log(y)
所以操作2的复杂度是 O(x * log(y))
我们要使得 O( max(x + ylog(y), xlog(y)) 尽可能小
根据基本不等式得出 当x==y时最小
=> n = x*y; x=y=sqrt(n);
#include <iostream> #include <string> #include <vector> #include <cstring> #include <cstdio> #include <map> #include <queue> #include <algorithm> #include <stack> #include <cstring> #include <cmath> #include <set> #include <vector> using namespace std; template <class T> inline bool rd(T &ret) { char c; int sgn; if (c = getchar(), c == EOF) return 0; while (c != '-' && (c<'0' || c>'9')) c = getchar(); sgn = (c == '-') ? -1 : 1; ret = (c == '-') ? 0 : (c - '0'); while (c = getchar(), c >= '0'&&c <= '9') ret = ret * 10 + (c - '0'); ret *= sgn; return 1; } template <class T> inline void pt(T x) { if (x < 0) { putchar('-'); x = -x; } if (x > 9) pt(x / 10); putchar(x % 10 + '0'); } typedef long long ll; typedef pair<ll, int> pii; const int inf = 1e9; const int N = 5e5 + 10; const int Block = 850;//700 int n, q; int ansl, ansr; ll a[N]; set<pii>::iterator it; struct Node { set<pii>x; ll b; inline void add(int l, int r, int val) { if (r - l + 1 == (int)x.size())b += val; else { for (int i = l; i <= r; i++) { x.erase({ a[i], i }); a[i] += val; x.insert({ a[i], i }); } } } inline void find(ll y) { y -= b; it = x.lower_bound({ y, -inf }); if (it == x.end() || (*it).first != y)return; ansl = min(ansl, (*it).second); it = x.upper_bound({ y, inf }); it--; ansr = max(ansr, (*it).second); } }y[Block]; int block; int main() { rd(n); rd(q); for (int i = 0; i < n; i++)rd(a[i]); block = 0; for (int i = 0; i < n; i += Block, block++) for (int j = 0; i + j < n && j < Block; j++) { y[block].x.insert({ a[i + j],i + j }); } int op, l, r, val; while (q--) { rd(op); if (op == 1) { rd(l); rd(r); rd(val); l--;r--; for (int i = l / Block; i <= r / Block; i++) y[i].add(max(l, i*Block), min(r, i*Block + Block - 1), val); } else { rd(val); ansl = inf, ansr = -inf; for (int i = 0; i < block; i++) y[i].find(val); if (ansr - ansl < 0)puts("-1"); else pt(ansr - ansl), putchar('\n'); } } return 0; }把set改掉。。:
#include <iostream> #include <string> #include <vector> #include <cstring> #include <cstdio> #include <map> #include <queue> #include <algorithm> #include <stack> #include <cstring> #include <cmath> #include <set> #include <vector> using namespace std; template <class T> inline bool rd(T &ret) { char c; int sgn; if (c = getchar(), c == EOF) return 0; while (c != '-' && (c<'0' || c>'9')) c = getchar(); sgn = (c == '-') ? -1 : 1; ret = (c == '-') ? 0 : (c - '0'); while (c = getchar(), c >= '0'&&c <= '9') ret = ret * 10 + (c - '0'); ret *= sgn; return 1; } template <class T> inline void pt(T x) { if (x < 0) { putchar('-'); x = -x; } if (x > 9) pt(x / 10); putchar(x % 10 + '0'); } typedef long long ll; typedef pair<int, int> pii; const int inf = 1e9; const int N = 5e5 + 10; const int Block = 850;//700 int n, q; int ansl, ansr; struct Node { struct Point { ll a; int id; Point(ll _a = 0, ll _id = 0) :a(_a), id(_id) {} bool operator<(const Point&x)const { if (x.a != a)return a < x.a; return id < x.id; } }x[Block], tmp; ll b; int top; inline void Sort() { sort(x, x + top); } inline void add(int l, int r, int val) { if (r - l + 1 == top)b += val; else { for (int i = 0; i < top; i++) if (l <= x[i].id && x[i].id <= r) x[i].a += val; Sort(); } } inline void find(ll y) { y -= b; if (y < x[0].a || x[top - 1].a < y)return; tmp = { y, -inf }; int l = lower_bound(x, x + top, tmp) - x; if (l == top || x[l].a != y)return; tmp.id = inf; int r = lower_bound(x, x + top, tmp) - x - 1; ansl = min(ansl, x[l].id); ansr = max(ansr, x[r].id); } }y[Block]; int a[N], block; int main() { rd(n); rd(q); for (int i = 0; i < n; i++)rd(a[i]); block = 0; for (int i = 0; i < n; i += Block, block++) { for (int j = 0; i + j < n && j < Block; j++) { y[block].x[j].a = a[i + j]; y[block].x[j].id = i + j; y[block].top++; } y[block].Sort(); } int op, l, r, val; while (q--) { rd(op); if (op == 1) { rd(l); rd(r); rd(val); l--;r--; for (int i = l / Block; i <= r / Block; i++) y[i].add(max(l, i*Block), min(r, i*Block + Block - 1), val); } else { rd(val); ansl = inf, ansr = -inf; for (int i = 0; i < block; i++) y[i].find(val); if (ansr - ansl < 0)puts("-1"); else pt(ansr - ansl), putchar('\n'); } } return 0; }