1 条题解
-
0
题意:
长度序列上 次区间 , 查询区间历史 时长。
题解:
序列和时间二维平面上的矩形加柱形 查询,扫描线转化成区间加区间 查询。
#define rep(i,a,b) for(int i=(a);i<=(b);++i) #define per(i,a,b) for(int i=(a);i>=(b);--i) #define blk(x) ((x) / bs) #define hob(x) ((x)*bs) #define eob(x) min(((x)+1) * bs - 1, n) using namespace std; const int maxn = 1e5, bs = 316, nb = maxn / bs + 10; struct block { ll a[maxn + 10], tag[nb + 10]; int ovi[maxn + 10], buf1[bs + 10], buf2[bs + 10], n; void init(int _n) { n = _n; rep(i,0,n) ovi[i] = i; } void add(int x, int c) { int bx = blk(x); rep(i,bx + 1, blk(n)) tag[i] += c; int s = hob(bx), t = eob(bx); rep(i,x,t) a[i] += c; int e1 = -1, e2 = -1, p1 = 0, p2 = 0; rep(i,s,t) if(ovi[i] >= x) buf1[++ e1] = ovi[i]; else buf2[++ e2] = ovi[i]; rep(i,s,t) ovi[i] = (p2 > e2 || p1 <= e1 && a[buf1[p1]] < a[buf2[p2]]) ? buf1[p1 ++] : buf2[p2 ++]; } int qry(int x, int c) { int bx = blk(x), ans = 0; rep(i,blk(0),bx - 1) { int s = hob(i), t = eob(i); if(a[ovi[t]] + tag[i] < c) continue; if(a[ovi[s]] + tag[i] >= c) { ans += t - s + 1; continue; } while(s < t) { int mid = (s + t) >> 1; if(a[ovi[mid]] + tag[i] >= c) t = mid; else s = mid + 1; } ans += eob(i) - s + 1; } rep(i,hob(bx),x) ans += a[i] + tag[bx] >= c; return ans; } } blker; struct node { int x, c; }; vector< node > v[maxn + 10]; vector< pair<node, int> > q[maxn + 10]; int ans[maxn + 10], a[maxn + 10]; int main() { int n, totQ, opt, l, r, x, p, y; scanf("%d %d", &n, &totQ); rep(i,1,n) scanf("%d", a + i); blker.init(totQ); memset(ans, -1, sizeof(ans)); rep(qr,1,totQ) { scanf("%d", &opt); if(opt == 1) { scanf("%d %d %d", &l, &r, &x); v[l].push_back({qr, x}); if(r != n) v[r + 1].push_back({qr, -x}); } else if(opt == 2) { scanf("%d %d", &p, &y); q[p].push_back({{qr - 1, y}, qr}); } } rep(i,1,n) { for(auto &it : v[i]) { blker.add(it.x, it.c); } for(auto &it : q[i]) { ans[it.second] = blker.qry(it.first.x, it.first.c - a[i]); } } rep(i,1,totQ) if(~ans[i]) printf("%d\n", ans[i]); return 0; }
- 1
信息
- ID
- 2796
- 时间
- 2000ms
- 内存
- 500MiB
- 难度
- 6
- 标签
- 递交数
- 1
- 已通过
- 1
- 上传者