bzoj3110 [Zjoi2013]K大数查询
传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=3110
【题解】
整体二分,把op=1的c变成n-c+1这样值域就是[1,2n+1],然后就是第k小了这样好做,最后输出记得变回来。
我们定义过程solve(l,r,al,ar)表示答案在[l,r],待操作[al,ar]
那么我们把c<=mid的操作全部做上去,然后对询问和操作分类,撤回操作即可。
# include <stdio.h> # include <string.h> # include <iostream> # include <algorithm> // # include <bits/stdc++.h> using namespace std; typedef long long ll; typedef long double ld; typedef unsigned long long ull; const int M = 5e5 + 10; const int mod = 1e9+7; # define RG register # define ST static int n, Q; struct quest { int op, a, b, c; quest() {} quest(int op, int a, int b, int c) : op(op), a(a), b(b), c(c) {} }a[M]; struct BIT { int n; ll c[M]; # define lb(x) (x&(-x)) inline void set(int _n) { n = _n; memset(c, 0, sizeof c); } inline void edt(int x, int d) { for (; x<=n; x+=lb(x)) c[x] += d; } inline ll sum(int x) { ll ret = 0; for (; x; x-=lb(x)) ret += c[x]; return ret; } }; struct BIT2 { int n; BIT a, b; inline void set(int _n) { n = _n; a.set(n), b.set(n); } inline void edt(int x, int y, int d) { a.edt(x, d); a.edt(y+1, -d); b.edt(x, (ll)d*x); b.edt(y+1, -(ll)d*(y+1)); } inline ll sum(int x) { return a.sum(x) * (x+1) - b.sum(x); } inline ll sum(int x, int y) { return sum(y) - sum(x-1); } }T; ll cur[M]; int ans[M], id[M], t1[M], t2[M]; inline void solve(int l, int r, int al, int ar) { if(al > ar) return ; // printf("%d %d %d %d\n", l, r, al, ar); if(l == r) { for (int i=al; i<=ar; ++i) if(a[id[i]].op == 2) ans[id[i]] = l; return; } // for (int i=al; i<=ar; ++i) // cout << id[i] << ","; // cout << endl << endl; ll tem; int mid = l+r>>1, t1n, t2n; t1n = t2n = 0; for (int i=al; i<=ar; ++i) { int x = id[i]; if(a[x].op == 1) { if(a[x].c <= mid) { t1[++t1n] = x; T.edt(a[x].a, a[x].b, 1); } else t2[++t2n] = x; } else { if((tem = cur[x] + T.sum(a[x].a, a[x].b)) >= a[x].c) t1[++t1n] = x; else t2[++t2n] = x, cur[x] = tem; } } for (int i=al; i<=ar; ++i) { int x = id[i]; if(a[x].op == 1) { if(a[x].c <= mid) T.edt(a[x].a, a[x].b, -1); } } int tn = al-1; for (int i=1; i<=t1n; ++i) id[++tn] = t1[i]; t1n = tn; for (int i=1; i<=t2n; ++i) id[++tn] = t2[i]; solve(l, mid, al, t1n); solve(mid+1, r, t1n+1, ar); } int main() { cin >> n >> Q; for (int i=1; i<=Q; ++i) { scanf("%d%d%d%d", &a[i].op, &a[i].a, &a[i].b, &a[i].c); if(a[i].op == 1) a[i].c = n - a[i].c + 1; id[i] = i; } // for (int i=1; i<=Q; ++i) printf("%d %d %d %d\n", a[i].op, a[i].a, a[i].b, a[i].c); T.set(n); solve(1, n+n+1, 1, Q); for (int i=1; i<=Q; ++i) if(a[i].op == 2) printf("%d\n", n - ans[i] + 1); return 0; }