学习笔记(二) 区间问题

一、ST表(RMQ或RGQ问题等)

ST算法处理静态空间的RMQ问题效率相当高,预处理时间复杂度 O(nlogn) ,查询时间复杂度 O(1)。思路同莫队算法类似,同为分块+处理,但是ST完全不支持修改,如果只有查询,ST查询效率远高于莫队。

思路:DP预处理(倍增法)+贪心查询

首先,ST需要分块,通过倍增思路分块。第一组全分为长度为1的块,第二组全分为长度为2的块,第三组长度为4,倍增地以此类推。注意这里的分块每个块之间不是完全互斥的,和归并排序中的分组完全相反,这里的分块是分别以每个元素为头找到长度为2^(组数-1) 的块,只要块的尾没到数组的结尾,就把每个元素都找到这样的块。如此,总共需要logn个块,用二维数组存储,应该类似于 dp[logn][n] 这样,dp[i][j] 代表第i+1组中以j为首元素的块,而记载的答案自然为要找的最大值或最小值。

然后,分块思路和存储方式找到了,第一组即 dp[0][j] 自然为原数组。通过转移方程:

dp[i][j]=min{dp[i-1][j],dp[i-1][j+2^(i-1)]}

递推得到全部的信息。转移方程代表第i+1组以j为首元素的块的最小值为上一组可以将其平分的两个块最小值的最小值。

因为最值是符合贪心的,所以只要两个小区间能完全覆盖住大区间(两个小区间重叠也可以),那么就可以贪心的递推。

最后便是如何查询了,按照上述所言,对于L到R之间的最值查询,len=R-L+1,只要找到两个小块重叠刚好完全覆盖这个长度就好,小块的长度x满足 x<=len<=2x 就好,即小块在第log(len)+1组。令k=log(lR-L+1),那么答案就出来了:

ans=min{dp[k][L],dp[k][R-2^k+1]}

eg.洛谷P2880

附链接https://www.luogu.com.cn/problem/P2880

#include <bits/stdc++.h>
#define lowbit(x) ((x) & -(x))
#define rep(i,l,r) for(register int i=l;i<=r;i++)
using namespace std;

const int N = 5e4 + 5;
const int INF = 0x3fffffff;
const double eps = 1e-6;
typedef long long ll;
const int modp = 1e6 + 37;

inline int read() {
	int x = 0, f = 1;
	char ch = getchar();
	while (ch < '0' || ch > '9') {
		if (ch == '-')
			f = -1;
		ch = getchar();
	}
	while (ch >= '0' && ch <= '9') {
		x = x * 10 + ch - 48;
		ch = getchar();
	}
	return x * f;
}

int n, q;
int l, r;
int Log[N];
int dp1[100][N];
int dp2[100][N];

void init() {
	Log[0] = -1;
	rep(i, 1, n) Log[i] = Log[i >> 1] + 1;
	rep(i, 1, Log[n]) {
		rep(j, 1, n) {
			if (j + (1 << i) - 1 <= n)
				dp1[i][j] = min(dp1[i - 1][j], dp1[i - 1][j + (1 << (i - 1))]);
		}
	}
	rep(i, 1, Log[n]) {
		rep(j, 1, n) {
			if (j + (1 << i) - 1 <= n)
				dp2[i][j] = max(dp2[i - 1][j], dp2[i - 1][j + (1 << (i - 1))]);
		}
	}
}

void solve() {
	int mina, maxa;
	int k = Log[r - l + 1];
	mina = min(dp1[k][l], dp1[k][r - (1 << k) + 1]);
	maxa = max(dp2[k][l], dp2[k][r - (1 << k) + 1]);
	cout << maxa - mina << endl;
}

int main() {
	ios::sync_with_stdio(0), cout.tie(0), cin.tie(0);
	n=read();
    q=read();
	rep(i, 1, n)  dp1[0][i] = dp2[0][i] = read();
	init();
	while (q--) {
		l = read();
		r = read();
		solve();
	}
	return 0;
}

同理,求取区间最大公约数问题一样解法。对于离线无需维护数组时用ST算法时间复杂度短且非常好写(只需记住两个dp转移方程就好)。

二、线段树

hdu 4027

#include <bits/stdc++.h>
#define lowbit(x) ((x) & -(x))
#define rep(i,l,r) for(register int i=l;i<=r;i++)
using namespace std;

const int N = 1e5 + 10;
const int INF = 0x3fffffff;
const double eps = 1e-6;
typedef long long ll;
const int modp = 1e6 + 37;

inline int read() {
	int x = 0, f = 1;
	char ch = getchar();
	while (ch < '0' || ch > '9') {
		if (ch == '-')
			f = -1;
		ch = getchar();
	}
	while (ch >= '0' && ch <= '9') {
		x = x * 10 + ch - 48;
		ch = getchar();
	}
	return x * f;
}

ll n, m;
ll a[N];
ll tree[N << 2];

ll ls(ll x) {
	return x << 1;
}

ll rs(ll x) {
	return x << 1 | 1;
}

void push_up(ll p) {
	tree[p] = tree[ls(p)] + tree[rs(p)];
}

void addtag(ll p, ll pl, ll pr) {
	if (tree[p] > (pr - pl + 1)) {
		if (pl == pr) {
			tree[p] = (ll)sqrt(tree[p]);
			return;
		}
		ll mid = (pl + pr) >> 1;
		addtag(ls(p), pl, mid);
		addtag(rs(p), mid + 1, pr);
		push_up(p);
	}
}

ll build(ll p, ll pl, ll pr) {
	if (pr == pl) {
		tree[p] = a[pl];
		return tree[p];
	}
	ll mid = (pl + pr) >> 1;
	tree[p] = build(ls(p), pl, mid) + build(rs(p), mid + 1, pr);
	return tree[p];
}

void updata(ll l, ll r, ll p, ll pl, ll pr) {
	if (l <= pl && r >= pr) {
		addtag(p, pl, pr);
		return;
	}
	ll mid = (pl + pr) >> 1;
	if (l <= mid)
		updata(l, r, ls(p), pl, mid);
	if (r > mid)
		updata(l, r, rs(p), mid + 1, pr);
	push_up(p);
}

ll sum(ll l, ll r, ll p, ll pl, ll pr) {
	if (l <= pl && r >= pr) {
		return tree[p];
	}
	ll res = 0;
	ll mid = (pl + pr) >> 1;
	if (l <= mid)
		res += sum(l, r, ls(p), pl, mid);
	if (r > mid)
		res += sum(l, r, rs(p), mid + 1, pr);
	return res;
}

int main() {
	//ios::sync_with_stdio(0), cout.tie(0), cin.tie(0);
	ll k = 0;
	while (scanf("%lld", &n) != EOF) {
		for (ll i = 1; i <= n; i++)
			scanf("%lld", &a[i]);
		build(1, 1, n);
		scanf("%lld", &m);
		++k;
		cout << "Case #" << k << ":" << endl;
		while (m--) {
			ll t, x, y;
			scanf("%lld%lld%lld", &t, &x, &y);
			if (x > y)
				swap(x, y);
			if (t == 0)
				updata(x, y, 1, 1, n);
			else
				cout << sum(x, y, 1, 1, n) << endl;
		}
	}
	return 0;
}


hdu 4578

#include <bits/stdc++.h>
#define lowbit(x) ((x) & -(x))
#define rep(i,l,r) for(register int i=l;i<=r;i++)
using namespace std;

const int N = 1e5 + 10;
const int INF = 0x3fffffff;
const double eps = 1e-6;
typedef int ll;
const int modp = 10007;

inline int read() {
	int x = 0, f = 1;
	char ch = getchar();
	while (ch < '0' || ch > '9') {
		if (ch == '-')
			f = -1;
		ch = getchar();
	}
	while (ch >= '0' && ch <= '9') {
		x = x * 10 + ch - 48;
		ch = getchar();
	}
	return x * f;
}

ll n, m;
ll tree1[N << 2];
ll tag1[N << 2];
ll tree2[N << 2];
ll tag2[N << 2];
ll tree3[N << 2];
ll tag3[N << 2];

ll ls(ll x) {
	return x << 1;
}

ll rs(ll x) {
	return x << 1 | 1;
}

void push_up(ll p) {
	tree1[p] = (tree1[ls(p)] + tree1[rs(p)]) % modp;
	tree2[p] = (tree2[ls(p)] + tree2[rs(p)]) % modp;
	tree3[p] = (tree3[ls(p)] + tree3[rs(p)]) % modp;
}


void addtag1(ll p, ll d, ll pl, ll pr) { //加法稍麻烦,参考公式
	tree3[p] = ((tree3[p] + (pr - pl + 1) * d % modp * d % modp * d % modp) % modp + 3 * d *
	            (tree2[p] + tree1[p] * d % modp) % modp) % modp;
	tree2[p] = (tree2[p] + (pr - pl + 1) * d % modp * d % modp + 2 * tree1[p] * d % modp) % modp;
	tree1[p] = (tree1[p] + (pr - pl + 1) * d % modp) % modp;
	tag1[p] = (tag1[p] + d) % modp;
}

void addtag2(ll p, ll d, ll pl, ll pr) { //乘法注意,如果有加法标记,将加法标记也乘上乘法标记
	tag1[p] = (tag1[p] * d) % modp;
	tag2[p] = (tag2[p] * d) % modp;
	tree1[p] = tree1[p] * d % modp;
	tree2[p] = tree2[p] * d % modp * d % modp;
	tree3[p] = tree3[p] * d % modp * d % modp * d % modp;
}

void addtag3(ll p, ll d, ll pl, ll pr) { //change时清空加法和乘法标记
	tag1[p] = tag3[p] = 0;
	tag2[p] = 1;
	tag3[p] = d;
	tree1[p] = (pr - pl + 1) * d % modp;
	tree2[p] = (pr - pl + 1) * d % modp * d % modp;
	tree3[p] = (pr - pl + 1) * d % modp * d % modp * d % modp;
}

void pd1(ll p, ll pl, ll pr) { //加
	if (tag1[p]) {
		ll mid = (pl + pr) >> 1;
		addtag1(ls(p), tag1[p], pl, mid);
		addtag1(rs(p), tag1[p], mid + 1, pr);
		tag1[p] = 0;
	}
}

void pd2(ll p, ll pl, ll pr) { //乘
	if (tag2[p] != 1) {
		ll mid = (pl + pr) >> 1;
		addtag2(ls(p), tag2[p], pl, mid);
		addtag2(rs(p), tag2[p], mid + 1, pr);
		tag2[p] = 1;
	}
}

void pd3(ll p, ll pl, ll pr) { //change
	if (tag3[p]) {
		ll mid = (pl + pr) >> 1;
		addtag3(ls(p), tag3[p], pl, mid);
		addtag3(rs(p), tag3[p], mid + 1, pr);
		tag3[p] = 0;
	}
}

void push_down(ll p, ll pl, ll pr) { //先change然后再乘最后加
	pd3(p, pl, pr);
	pd2(p, pl, pr);
	pd1(p, pl, pr);
}

void build(ll p, ll pl, ll pr) {
	tag1[p] = tag3[p] = 0;
	tag2[p] = 1; //注意乘法标记初值为1
	if (pr == pl) {
		tree1[p] = tree2[p] = tree3[p] = 0;
		return;
	}
	ll mid = (pl + pr) >> 1;
	build(ls(p), pl, mid);
	build(rs(p), mid + 1, pr);
	push_up(p);
}

void updata(ll l, ll r, ll d, ll p, ll pl, ll pr, ll k) {
	if (l <= pl && r >= pr) {
		if (k == 1)
			addtag1(p, d, pl, pr);
		else if (k == 2)
			addtag2(p, d, pl, pr);
		else
			addtag3(p, d, pl, pr);
		return;
	}
	push_down(p, pl, pr);
	ll mid = (pl + pr) >> 1;
	if (l <= mid)
		updata(l, r, d, ls(p), pl, mid, k);
	if (r > mid)
		updata(l, r, d, rs(p), mid + 1, pr, k);
	push_up(p);
}

ll sum(ll l, ll r, ll p, ll pl, ll pr, ll k) {
	if (l <= pl && r >= pr) {
		if (k == 1)
			return tree1[p];
		else if (k == 2)
			return tree2[p];
		else
			return tree3[p];
	}
	push_down(p, pl, pr);
	ll res = 0;
	ll mid = (pl + pr) >> 1;
	if (l <= mid)
		res = (res + sum(l, r, ls(p), pl, mid, k)) % modp;
	if (r > mid)
		res = (res + sum(l, r, rs(p), mid + 1, pr, k)) % modp;
	return res % modp;
}

int main() {
	ios::sync_with_stdio(0), cout.tie(0), cin.tie(0);
	while (true) {
		cin >> n >> m;
		if (n == 0 && m == 0)
			break;
		build(1, 1, n);
		while (m--) {
			ll op, x, y, d;
			cin >> op >> x >> y >> d;
			if (x > y)
				swap(x, y);
			if (op != 4)
				updata(x, y, d, 1, 1, n, op);
			else {
				cout << sum(x, y, 1, 1, n, d) << endl;
			}
		}
	}
	return 0;
}


洛谷P6242

#include <bits/stdc++.h>
#define lowbit(x) ((x) & -(x))
#define rep(i,l,r) for(register int i=l;i<=r;i++)
using namespace std;

const int N = 5e5 + 5;
const int INF = 1e9 + 5; //0x3fffffff;
const double eps = 1e-6;
typedef long long ll;
const int modp = 1e6 + 37;

inline int read() {
	int x = 0, f = 1;
	char ch = getchar();
	while (ch < '0' || ch > '9') {
		if (ch == '-')
			f = -1;
		ch = getchar();
	}
	while (ch >= '0' && ch <= '9') {
		x = x * 10 + ch - 48;
		ch = getchar();
	}
	return x * f;
}

ll n, m;
ll a[N];
ll maa[N << 2];
ll numa[N << 2];
ll mab[N << 2];
ll suma[N << 2];
ll sea[N << 2];
ll tagma[N << 2];
ll tagse[N << 2];
ll taghisma[N << 2];
ll taghisse[N << 2];


ll ls(ll x) {
	return x << 1;
}

ll rs(ll x) {
	return x << 1 | 1;
}

void push_up(ll p) {
	suma[p] = suma[ls(p)] + suma[rs(p)];
	maa[p] = max(maa[ls(p)], maa[rs(p)]);
	mab[p] = max(mab[ls(p)], mab[rs(p)]);
	sea[p] = max(sea[ls(p)], sea[rs(p)]);
	if (maa[ls(p)] == maa[rs(p)]) {
		numa[p] = numa[ls(p)] + numa[rs(p)];
	} else {
		sea[p] = max(sea[p], min(maa[ls(p)], maa[rs(p)]));
		numa[p] = maa[ls(p)] > maa[rs(p)] ? numa[ls(p)] : numa[rs(p)];
	}
}

void addtag(ll p, ll pl, ll pr, ll t1, ll t2, ll t3, ll t4) {
	suma[p] += (t1 * numa[p] + (pr - pl + 1 - numa[p]) * t2);
	mab[p] = max(mab[p], t3 + maa[p]);
	maa[p] += t1;
	if (sea[p] != -INF)
		sea[p] += t2;
	taghisma[p] = max(taghisma[p], tagma[p] + t3), tagma[p] += t1;
	taghisse[p] = max(taghisse[p], tagse[p] + t4), tagse[p] += t2;
}

void push_down(ll p, ll pl, ll pr) {
	ll maxn = max(maa[ls(p)], maa[rs(p)]);
	ll mid = (pl + pr) >> 1;
	if (maxn == maa[ls(p)])
		addtag(ls(p), pl, mid, tagma[p], tagse[p], taghisma[p], taghisse[p]);
	else
		addtag(ls(p), pl, mid, tagse[p], tagse[p], taghisse[p], taghisse[p]);
	if (maxn == maa[rs(p)])
		addtag(rs(p), mid + 1, pr, tagma[p], tagse[p], taghisma[p], taghisse[p]);
	else
		addtag(rs(p), mid + 1, pr, tagse[p], tagse[p], taghisse[p], taghisse[p]);
	tagma[p] = tagse[p] = taghisma[p] = taghisse[p] = 0;
}

void build(ll p, ll pl, ll pr) {
	tagma[p] = tagse[p] = taghisma[p] = taghisse[p] = 0;
	if (pr == pl) {
		mab[p] = maa[p] = suma[p] = a[pl];
		sea[p] = -INF;
		numa[p] = 1;
		return;
	}
	ll mid = (pl + pr) >> 1;
	build(ls(p), pl, mid) ;
	build(rs(p), mid + 1, pr);
	push_up(p);
}

void updata1(ll l, ll r, ll d, ll p, ll pl, ll pr) {
	if (l <= pl && r >= pr) {
		addtag(p, pl, pr, d, d, d, d);
		return;
	}
	push_down(p, pl, pr);
	ll mid = (pl + pr) >> 1;
	if (l <= mid)
		updata1(l, r, d, ls(p), pl, mid);
	if (r > mid)
		updata1(l, r, d, rs(p), mid + 1, pr);
	push_up(p);
}

void updata2(ll l, ll r, ll d, ll p, ll pl, ll pr) {
	if (maa[p] <= d)
		return;
	if (l <= pl && r >= pr && sea[p] < d) {
		addtag(p, pl, pr, d - maa[p], 0, d - mab[p], 0);
		return;
	}
	push_down(p, pl, pr);
	ll mid = (pl + pr) >> 1;
	if (l <= mid)
		updata2(l, r, d, ls(p), pl, mid);
	if (r > mid)
		updata2(l, r, d, rs(p), mid + 1, pr);
	push_up(p);
}

ll sum(ll l, ll r, ll p, ll pl, ll pr) {
	if (l <= pl && r >= pr) {
		return suma[p];
	}
	push_down(p, pl, pr);
	ll res = 0;
	ll mid = (pl + pr) >> 1;
	if (l <= mid)
		res += sum(l, r, ls(p), pl, mid);
	if (r > mid)
		res += sum(l, r, rs(p), mid + 1, pr);
	return res;
}

ll qmaxa(ll l, ll r, ll p, ll pl, ll pr) {
	if (l <= pl && r >= pr) {
		return maa[p];
	}
	push_down(p, pl, pr);
	ll mid = (pl + pr) >> 1;
	ll res = -INF;
	if (l <= mid)
		res = max(qmaxa(l, r, ls(p), pl, mid), res);
	if (r > mid)
		res = max(qmaxa(l, r, rs(p), mid + 1, pr), res);
	return res;
}

ll qmaxb(ll l, ll r, ll p, ll pl, ll pr) {
	if (l <= pl && r >= pr) {
		return mab[p];
	}
	push_down(p, pl, pr);
	ll mid = (pl + pr) >> 1;
	ll res = -INF;
	if (l <= mid)
		res = max(qmaxb(l, r, ls(p), pl, mid), res);
	if (r > mid)
		res = max(qmaxb(l, r, rs(p), mid + 1, pr), res);
	return res;
}

int main() {
	n = read();
	m = read();
	for (ll i = 1; i <= n; i++)
		a[i] = read();
	build(1, 1, n);
	while (m--) {
		ll op, x, y;
		op = read();
		x = read();
		y = read();
		if (op == 1) {
			ll d;
			d = read();
			updata1(x, y, d, 1, 1, n);
		} else if (op == 2) {
			ll d;
			d = read();
			updata2(x, y, d, 1, 1, n);
		} else if (op == 3) {
			cout << sum(x, y, 1, 1, n) << endl;
		} else if (op == 4) {
			cout << qmaxa(x, y, 1, 1, n) << endl;
		} else {
			cout << qmaxb(x, y, 1, 1, n) << endl;
		}
	}
	return 0;
}


hdu1540

#include <bits/stdc++.h>
#define lowbit(x) ((x) & -(x))
#define rep(i,l,r) for(register int i=l;i<=r;i++)
using namespace std;

const int N = 5e4 + 10;
const int INF = 0x3fffffff;
const double eps = 1e-6;
typedef int ll;
const int modp = 1e6 + 37;

inline int read() {
	int x = 0, f = 1;
	char ch = getchar();
	while (ch < '0' || ch > '9') {
		if (ch == '-')
			f = -1;
		ch = getchar();
	}
	while (ch >= '0' && ch <= '9') {
		x = x * 10 + ch - 48;
		ch = getchar();
	}
	return x * f;
}

ll n, m;
ll tree[N];
stack<ll> st;

void init() {
	memset(tree, 0, sizeof(tree));
	rep(i, 1, n) tree[i] = lowbit(i);
	while (!st.empty())
		st.pop();
}

void updata(ll x, ll d) {
	while (x <= n) {
		tree[x] += d;
		x += lowbit(x);
	}
}

ll sum(ll x) {
	ll res = 0;
	while (x > 0) {
		res += tree[x];
		x -= lowbit(x);
	}
	return res;
}

bool check(ll l, ll r) {
	if (sum(r) - sum(l - 1) >= r - l + 1)
		return true;
	return false;
}

ll solve(ll x) {
	ll res = 0;
	ll l = 1, r = x + 1;
	while (l < r) {
		ll mid = (l + r) >> 1;
		if (check(mid, x))
			r = mid;
		else
			l = mid + 1;
	}
	ll pos1 = r;
	l = x;
	r = n;
	while (l < r) {
		ll mid = (l + r + 1) >> 1;
		if (check(x, mid))
			l = mid;
		else
			r = mid - 1;
	}
	ll pos2 = l;
	return pos2 - pos1 + 1;
}

int main() {
	//ios::sync_with_stdio(0), cout.tie(0), cin.tie(0);
	while (~scanf("%d%d", &n, &m)) {
		init();
		while (m--) {
			char op[10];
			scanf("%s", op);
			if (op[0] == 'D') {
				ll x;
				scanf("%d", &x);
				updata(x, -1);
				st.push(x);
			} else if (op[0] == 'Q') {
				ll x;
				scanf("%d", &x);
				ll ans = solve(x);
				printf("%d\n", ans);
			} else {
				ll x;
				x = st.top();
				st.pop();
				updata(x, 1);
			}
		}
	}
	return 0;
}

hdu 1542

#include <bits/stdc++.h>
#define lowbit(x) ((x) & -(x))
#define rep(i,l,r) for(register int i=l;i<=r;i++)
using namespace std;

const int N = 5e3 + 10;
const int INF = 0x3fffffff;
const double eps = 1e-6;
typedef long long ll;
const int modp = 1e6 + 37;

inline int read() {
	int x = 0, f = 1;
	char ch = getchar();
	while (ch < '0' || ch > '9') {
		if (ch == '-')
			f = -1;
		ch = getchar();
	}
	while (ch >= '0' && ch <= '9') {
		x = x * 10 + ch - 48;
		ch = getchar();
	}
	return x * f;
}

ll n;
double tree[N << 2];
int tag[N << 2];
double xx[N];

typedef struct scanl {
	double x1, x2, y;
	int io;
	bool operator <(const scanl &a) {
		return y < a.y;
	}
	scanl() {
	}
	scanl(double xx1, double xx2, double yy, int iio) {
		x1 = xx1, x2 = xx2, y = yy, io = iio;
	}
} Line;

Line line[N];

ll ls(ll p) {
	return p << 1;
}

ll rs(ll p) {
	return p << 1 | 1;
}

void push_up(ll p, ll pl, ll pr) {
	if (tag[p] > 0)
		tree[p] = xx[pr] - xx[pl];
	else if (pl + 1 == pr)
		tree[p] = 0;
	else
		tree[p] = tree[ls(p)] + tree[rs(p)];
}

void addtag(ll p, ll d, ll pl, ll pr) {
	tag[p] += d;
	if (tag[p] > 0)
		tree[p] = xx[pr] - xx[pl];
	else if (pl + 1 == pr)
		tree[p] = 0;
	else
		tree[p] = tree[ls(p)] + tree[rs(p)];
}

void updata(ll l, ll r, ll d, ll p, ll pl, ll pr) {
	if (l <= pl && r >= pr) {
		addtag(p, d, pl, pr);
		return;
	}
	if (pl + 1 == pr)
		return;
	ll mid = (pl + pr) >> 1;
	if (l <= mid)
		updata(l, r, d, ls(p), pl, mid);
	if (r > mid)
		updata(l, r, d, rs(p), mid, pr);
	push_up(p, pl, pr);
}


int main() {
	//ios::sync_with_stdio(0), cout.tie(0), cin.tie(0);
	int k = 0;
	while (~scanf("%d", &n)) {
		if (n == 0)
			break;
		int cnt = 0;
		rep(i, 1, n) {
			double x1, x2, y1, y2;
			scanf("%lf%lf%lf%lf", &x1, &y1, &x2, &y2);
			line[++cnt] = Line(x1, x2, y1, 1);
			xx[cnt] = x1;
			line[++cnt] = Line(x1, x2, y2, -1);
			xx[cnt] = x2;
		}
		sort(line + 1, line + cnt + 1);
		sort(xx + 1, xx + cnt + 1);
		int num = unique(xx + 1, xx + cnt + 1) - (xx + 1);
		memset(tree, 0, sizeof(tree));
		memset(tag, 0, sizeof(tag));
		double ans = 0;
		rep(i, 1, cnt) {
			ans += tree[1] * (line[i].y - line[i - 1].y);
			int l = lower_bound(xx + 1, xx + num + 1, line[i].x1) - xx;
			int r = lower_bound(xx + 1, xx + num + 1, line[i].x2) - xx;
			updata(l, r, line[i].io, 1, 1, num);
		}
		cout << "Test case #" << ++k << endl;
		printf("Total explored area: %.2lf\n", ans);
	}
	return 0;
}


全部评论

相关推荐

点赞 评论 收藏
分享
避坑恶心到我了大家好,今天我想跟大家聊聊我在成都千子成智能科技有限公司(以下简称千子成)的求职经历,希望能给大家一些参考。千子成的母公司是“同创主悦”,主要经营各种产品,比如菜刀、POS机、电话卡等等。听起来是不是有点像地推销售公司?没错,就是那种类型的公司。我当时刚毕业,急需一份临时工作,所以在BOSS上看到了千子成的招聘信息。他们承诺无责底薪5000元,还包住宿,这吸引了我。面试的时候,HR也说了同样的话,感觉挺靠谱的。于是,我满怀期待地等待结果。结果出来后,我通过了面试,第二天就收到了试岗通知。试岗的内容就是地推销售,公司划定一个区域,然后你就得见人就问,问店铺、问路人,一直问到他们有意向为止。如果他们有兴趣,你就得摇同事帮忙推动,促进成交。说说一天的工作安排吧。工作时间是从早上8:30到晚上18:30。早上7点有人叫你起床,收拾后去公司,然后唱歌跳舞(销售公司都这样),7:55早课(类似宣誓),8:05同事间联系销售话术,8:15分享销售技巧,8:30经理训话。9:20左右从公司下市场,公交、地铁、自行车自费。到了市场大概10点左右,开始地推工作。中午吃饭时间大约是12:00,公司附近的路边盖饭面馆店自费AA,吃饭时间大约40分钟左右。吃完饭后继续地推工作,没有所谓的固定中午午休时间。下午6点下班后返回公司,不能直接下班,需要与同事交流话术,经理讲话洗脑。正常情况下9点下班。整个上班的一天中,早上到公司就是站着的,到晚上下班前都是站着。每天步数2万步以上。公司员工没有自己的工位,百来号人挤在一个20平方米的空间里听经理洗脑。白天就在市场上奔波,公司的投入成本几乎只有租金和工资,没有中央空调。早上2小时,晚上加班2小时,纯蒸桑拿。没有任何福利,节假日也没有3倍工资之类的。偶尔会有冲的酸梅汤和西瓜什么的。公司的晋升路径也很有意思:新人—组长—领队—主管—副经理—经理。要求是业绩和团队人数,类似传销模式,把人留下来。新人不能加微信、不能吐槽公司、不能有负面情绪、不能谈恋爱、不能说累。在公司没有任何坐的地方,不能依墙而坐。早上吃早饭在公司外面的安全通道,未到上班时间还会让你吃快些不能磨蹭。总之就是想榨干你。复试的时候,带你的师傅会给你营造一个钱多事少离家近的工作氛围,吹嘘工资有多高、还能吹自己毕业于好大学。然后让你早点来公司、无偿加班、抓住你可能不会走的心思进一步压榨你。总之,大家在找工作的时候一定要擦亮眼睛,避免踩坑!———来自网友
qq乃乃好喝到咩噗茶:不要做没有专业门槛的工作
点赞 评论 收藏
分享
评论
点赞
2
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务