学习笔记(二) 区间问题

一、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;
}


全部评论

相关推荐

04-26 14:36
已编辑
郑州信息科技职业学院 Java
由于高考成绩不是很理想,听取了张雪峰老师的建议,优先选了专业并且当时的想法就是选一个能赚钱的专业,于是最终选择了报了一个能收留我的有计算机专业的学校。当时听张雪峰老师说河南的学习氛围很好,所以就想去体验一下,事实雀食如张雪峰老师所说,大家都一股脑的铺在学习这条路上。可能是因为那边氛围导致的吧,我一开始想的也是卷学习卷绩点,所以大一的时候就一直在学习硬试教育的一些东西,学期结束了,排名出来的时候中上水平吧,据我了解保研的只有前5名可能会有机会,当时的心里就想着,我这成绩再卷也卷不到哪去了,并且保研也无望了,总结的说,一些事情只有真正做了才知道是不是自己所追求的。说了很多废话吧,剩下的关于学校的就长话短说了吧。大二很多专业课基本上要从早八上到晚上,但基本上我都是不去,不如自学现在新媒体技术这么发达,并且还可以学一下自己需要的技术栈,由于学校的课程原因对其他的技术栈不是很了解,所以,一心就投入在Java这个方向了,但是,Python也会学一下,这是因为加入实验室,实验室老师是做人工智能方向的缘故。现在回想,我大二当时还是学的太慢了,还有就是信息差太大了,出来工作之后才发现有些佬们已经大二就出来实习,并且八股就背的滚瓜烂熟了。只能说这里的学习氛围很好吧,走廊里都是背书刷题的声音,跟身边的同学和实验室的同学谈是否直接就业的事,他们要么都是说考研,要么对直接就业很含糊,可能是因为觉得自己学的还不够吧,我想说,学的不够就干中学呗,反正,我先迈出去这步再说。到了大三上还是没有找工作的打算,因为身边的人也都还没有这个意识吧,现在跟了身边的同事聊天才知道,我的信息差太大了。到了大三下刚开始,我才开始正式的踏上求职路,当时的信息差还是很大的,根本就不敢碰瓷大厂,想着有一个公司能要再说吧,并且地域也限制的很死,只想着在本地找一下,因为怕学校找事(我想这是学校一贯操作了),在本地吧,他们大多数都是接受的线下面,一开始面了一个,可能自己比较摆也很悲观,就显得我很差吧,hr面完就没后续了,最终终于有一个面,并且也展示出自己的自信和对专业的理解了,最后,我也没想着这么多背调公司呀,当个备选什么的就直接去了。也算是我的第一家正式的公司吧(之前都是线上的码农兼职),干多了就发现,这个公司压根学不到东西,并且薪资低的,因为我是第一个进来的计算机实习生,有一个同事干了两三年的吧,带着我做的时候是真能学到东西,但是,最后那个同事离职了,我就只能和学艺术的老板直接汇报项目进度,一个学艺术的来指导我这个科班出身的就很离谱的好吧。最后,我也离职了,也跟前同事聊了很久,她说我是她见过大三就能学到这程度,已经超过很多人了,并且她当时在的时候还说我是内定能转正的。并且还说我真的可以去考研。我也仔细思考了一下,我决定让自己沉淀一下再出发吧,先备考了软件设计师,然后期末考,大三暑期的时候就充实自己的简历,并且也认识了一个某东的老哥,也用了内推码,教我了怎么写好简历量化成果之类的,总之,很感谢一路走来帮助我的人吧,并且我在边充实自己的同时也在边投递简历,但当时卡的也很死,要选base地在河南附近的,不像现在全国可飞。面了很多base地在学校附近的,然后,还有一个北京的py和杭州的java,最终就这两个地方给了offer,但是都是实习转正的,不是秋招offer,因为觉得Java的太卷了,然后,面试的时候也会感觉压力很大,所以就把杭州的那个拒了,去了北京的,北京是免费住的房子(三个月这是伏笔),当时觉得环境很好,但是合租室友的作息跟自己的作息不一样就很不习惯,于是,我就想着要是三个月后我一定要找一个单间的哪怕破一点。北京这个公司吧就很像国企的感觉,早九晚五,当月发当月工资,并且干的活接触的数据量都不是很大,就是干了很多杂活,并且mentor和部门的领导都不是技术出身,所以,我能学到的东西少之又少,但是吧,学习是自己的事,而且这部门不是很忙对于实习生来说,我完全可以学自己的东西(前提是不被发现)。到最后这个部门的氛围就很微妙,我遇到不会的问他们我应该怎么做的时候,他们说让我自己想,我当时就想说,神人一个,啥都不说让我自己干,干出来又不满意,你说你让我干py的东西你不会我就不说啥了,让我干无关代码的东西,让我调研项目应该做些什么内容,现在回想都是泪呀,我就这样被欺压的过完了三个月,最后免费住的地方也到期了,伏笔来了,最后,找我谈话说你技术可以了能看出来,因为你也自己独立完成了消息通知那一块内容嘛,但是,由于我们部门干的活比较杂并且我也缺少一些电力相关的一些知识,所以,觉得不合适。(OS:其实我对每一份工作都是真心换真心的,并且这些电力知识我也知道我有一点欠缺所以我也有自己再学习,你们啥也不教我,最后把屎盆子把我头上扣)最后,回到了学校,心态也发生了变化,想着做啥都不如找一个稳定的工作重要,想着回家沉淀吧,少年终有出头日。但是,计划赶不上变化,之前那个同事,内推了我去她现在的公司,并且是做AI应用的也是我想接触的,并且还是与我上家的业务场景类似的,真的感谢那个同事,俗话说:千里马常有而伯乐不常有。并且那里的部门领导也很好,并且说我虽然不是电力相关出身的,但是能做的这样已经很不错了,所以DDDD,由于各种不可抗力因素吧,还是想找一个离家近,然后不是很像小作坊的感觉(这个公司虽然比较小,但是比之前那个大的公司的氛围和待遇一点都不差的好吧甚至更好)。最终,在学校也呆了一个月吧,也陆陆续续面了一个月有一个C厂的面答的都挺好直接就谈薪了,但是风评不好还是保命要紧,还有各种的中小厂面吧,但感觉都不是自己想要的,只是想刷刷面试经验吧(这是某东哥告诉我的,与其一直改简历不如去多面)。最后,在校期间面了一个比较合适的某鸦智能,一直推进到了HR面,但是最后被横向了,开始复盘,被横向了属实是没招了,经历了这么多大风大浪什么场面没见过。过年期间,求职路线关闭,把自己缺少的技术栈和简历中的项目业务理清楚说明白。年过完就要开始加入找工作大军中了,把节前没面完的先面了,节后一开始就是某鸟的HRG面,聊的就很憋屈的感觉,问我技术方面的,说我说的很像AI的(我心想跟你说具体的细节你又说我不想听技术的,说的比较宽泛浅显说我AI)。最后,反正体验感不是很好的结束了吧。说一个星期等通知,等了两个星期才说是通过的(我认为是排名靠前的那些人没去,顺位到我了)。那你既然这样说了,那我就接受吧。还没入职就问我要身份证信息要这要那的,最后都给过去了,说HC调整,要重新review,又又又一次被恶心到了。后面就是陆续的沉淀面试等,我当时的重心已经完全的想着私企没人要,就去试试考公和考央国企了,毕竟我的履历不看学历的话放到电网当中还是可以的。私企的话有一个外企洋里洋气的说话,问我怎么口语这么好?我说这叫智取,宝贝。虽然这个tek外企过了,但是还有一个openday要去线下,来回的衣食住行不是很方便也不是很想去所以就拒绝了没去。后来就收到了,国网网申通过的通知,说实话,我之前问了很多我们学校历年有没有考央国企之类的案例,很显然都不知道,也可以说少之又少吧,于是我就奔赴京城进京赶考,唉,时间不太合适就想着算了吧,再等等,好事多磨,宁缺毋滥吧。金三银四终于等来了面试的机会,这个岗位我只能说我不是很熟悉,但是语言这东西吧都是相通的,重要的是我要把其中的内核搞懂,梳理清楚业务逻辑。最终,来到了这家公司,目前来说是我遇到过最好的了,能有hc且不是要通过实习评估的那种,并且合同期限是三年的,并且是12%的公积金。我认为这就是我所遇到的最好的了。希望能真心换真心吧,不再把我当创口贴/路边一条了,并且也遇到了很多优秀的同事。总的来说,就是要是能重来我要选李白。我肯定会打破这些信息差,后悔知道的太晚,并且跟优秀的人聊天说话真的可以学到很多东西,之前上文提到的贵人就不说了,说说最近的,他是跟我一届,学校后缀甚至不如我的后缀,但是真正了解的才会知道真是佬👍,他跟我找工作的时间线差不多,但是他在中大厂甚至大厂都呆过,因为跟他聊了才知道我当时的信息差有多大,并且毅力也是我甚至…都没有的。并且也听说了他们学校找工作的氛围很好,不像我阿巴阿巴阿巴,只有考研等相关的一些。并且说的一些观点都是很认同的。总之,希望能在这好好的吧,我真的不想经历大起大落了。经历了,打招呼挂,简历挂,一面挂,HR面挂,offer挂的,现在的心态已经放宽了很多了,但是难过还是有的,希望这家公司诚不欺我吧。也祝大家遇到自己的梦中情厂
选择和努力,哪个更重要?
点赞 评论 收藏
分享
评论
点赞
2
分享

创作者周榜

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