1. 程式人生 > 其它 >Android保活技術實現,騰訊大佬推薦分享《Android程序保活入門與實戰》,乾貨滿滿!

Android保活技術實現,騰訊大佬推薦分享《Android程序保活入門與實戰》,乾貨滿滿!

比較好的線段樹二分.

先考慮沒有修改如何做:

對於一個 $\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; 
}