Android保活技術實現,騰訊大佬推薦分享《Android程序保活入門與實戰》,乾貨滿滿!
阿新 • • 發佈:2021-10-18
比較好的線段樹二分.
先考慮沒有修改如何做:
對於一個 $\mathrm{y}$, 先找到第一個可以選的 $\mathrm{a[i]}$, 然後儘量選這個連續段.
顯然,每當一個連續段停止時 $\mathrm{y}$ 的規模至少縮小了 $\mathrm{\frac{1}{2}}$.
所以,連續段的個數不會超過 $\mathrm{log n}$.
然後靜態做的話這個東西直接線上段樹上搜索一下就行.
如果加上修改,就直接打 $\mathrm{lazy}$ 標記.
直接查詢的話會比較麻煩,可以將 $\mathrm{y}$ 增大前 $\mathrm{x-1}$ 的和強制從 $1$ 開始選.
#include <cstdio> #include <vector> #include <cstring> #include <algorithm> #define N 200009 #define pb push_back #define ll long long #define ls now << 1 #define rs now << 1 | 1 #define setIO(s) freopen(s".in","r",stdin) using namespace std; ll sum[N<<2]; int n,Q,a[N],len[N<<2],lazy[N<<2],mi[N<<2]; void mark(int now, int v) { lazy[now]=mi[now]=v; sum[now] = 1ll * len[now] * v; } void pushdown(int now) { if(lazy[now]) { mark(ls, lazy[now]); mark(rs, lazy[now]); lazy[now] = 0; } } void pushup(int now) { mi[now] = min(mi[ls], mi[rs]); sum[now] = sum[ls] + sum[rs]; } void build(int l, int r, int now) { len[now] = r - l + 1; if(l == r) { mi[now] = sum[now] = a[l]; return ; } int mid=(l+r)>>1; build(l, mid, ls); build(mid + 1, r, rs); pushup(now); } void update(int l,int r,int now,int L,int R,int v) { if(l>=L&&r<=R) { mark(now, v); return ; } pushdown(now); int mid=(l+r)>>1; if(L<=mid) update(l, mid, ls, L, R, v); if(R>mid) update(mid + 1, r, rs, L, R, v); pushup(now); } int query(int l, int r, int now, ll &v) { if(v < mi[now]) return 0; if(l == r) { int d = 0; if(sum[now] <= v) v -= sum[now], d = 1; return d; } pushdown(now); int mid=(l+r)>>1; if(mi[ls] > v) return query(mid + 1, r, rs, v); else { if(sum[ls] <= v) { v -= sum[ls]; return len[ls] + query(mid + 1, r, rs, v); } else { int dl = query(l, mid, ls, v); int dr = query(mid+1,r,rs, v); return dl + dr; } } } // 第一個小於 v 的位置. int search(int l,int r,int now,int v) { if(l == r) { return l; } pushdown(now); int mid = (l + r) >> 1; if(mi[ls] < v) return search(l, mid, ls, v); else return search(mid + 1, r, rs, v); } ll get(int l,int r,int now,int L,int R) { if(l >= L && r <= R) { return sum[now]; } pushdown(now); int mid=(l+r)>>1; if(L<=mid&&R>mid) { return get(l,mid,ls,L,R)+get(mid+1,r,rs,L,R); } else if(L<=mid) return get(l,mid,ls,L,R); else return get(mid+1,r,rs,L,R); } int main() { // setIO("input"); scanf("%d%d",&n,&Q); for(int i=1;i<=n;++i) { scanf("%d",&a[i]); } build(1, n, 1); for(int i=1;i<=Q;++i) { int op,x,y; scanf("%d%d%d",&op,&x,&y); if(op == 1) { // [1, x] 與 y 取 max. if(mi[1] < y) { int pos = search(1, n, 1, y); if(pos <= x) { update(1, n, 1, pos, x, y); } } } else { ll o = 0; if(x > 1) { o = get(1, n, 1, 1, x - 1); } o += y; printf("%d\n", query(1, n, 1, o) - (x - 1)); } } return 0; }