GDKOI2014「内存分配」

题目

Description
小明的机器上运行着 nn 个程序P1,P2,,PnP_1,P_2,…,P_n ,其中程序 PiP_i 占用着 aia_i 个单位的内存,仍需要 bib_i 个单位的内存这个程序才能结束。小明可以为程序 PiP_i 分配至少 bib_i 个单位的空闲内存,结束这个程序。当程序 PiP_i 结束的时候,它会把它之前占用的 aia_i 个单位的内存和分配的 bib_i 个单位的内存一起释放,而小明可以把这些内存回收回来,与原来的空闲内存组成新的空闲内存小明想知道,他机器上的空闲内存至少应该是多少个单位,他的所有程序才有可能全部运行完。除此之外,每经过一分钟,小明的机器上都有一个程序 PjP_j 发生改变,即 aj,bja_j,b_j 变成了aj,bja'_j,b'_j。注意,同一个程序有可能会变化多次。你能帮小明计算,每次程序发生变化之后,系统上的空闲内存至少应该是多少个单位吗?

Sample Input

2 3
1 4
1 4
2 2 1
2 1 1
1 1 1

Sample Output

2
3
1

思路

把所有程序按照所需空间从小到大排好序,全部合并起来就可以得出最终答案,也就是树根。
对于修改操作,需要把所有程序(包括修改后)全部按照所需空间排序,一开始把所有原程序的位置从空程序修改为它本身。
修改时把原程序在所有程序排名的那个节点变成空程序 (0,0),再把新程序的位置从空程序变成新的程序 (a,b) 。只需要在线段树上单点修改就可以解决了。(竟然真的用到了!!单点修改!!)
时间复杂度为 O(nlogn)O(n\log n)

#include <cstdio>
#include <algorithm>
#define re register
using namespace std;
#define maxn 100005
#define _maxn 1000005

typedef long long ll;
struct node {
	int a, b, site, num;
} T[200005];
int qry[maxn], orig[maxn];
ll a[_maxn], b[_maxn];
bool exist[_maxn];

bool cmp(node x, node y) {
	return x.b<y.b || x.b==y.b && x.a>y.a;
}

void push_up(int now) {
	int L_son=now<<1, R_son=now<<1|1;
	a[now]=a[L_son]+a[R_son];
	b[now]=max(b[L_son], b[R_son]-a[L_son]);
}

void build(int now, int L, int R) {
	if (L==R) {
		if (!T[L].num) {
			a[now]=T[L].a;
			b[now]=T[L].b;
			exist[now]=1;
		}
		return;
	}
	
	int mid=(L+R)>>1;
	int L_son=now<<1, R_son=now<<1|1;
	build(L_son, L, mid);
	build(R_son, mid+1, R);
	
	push_up(now);
}

void update(int now, int L, int R, int x) {
	if (L==R) {
		if (exist[now]) {
			a[now]=b[now]=0;
			exist[now]=0;
		}
		else {
			a[now]=T[L].a;
			b[now]=T[L].b;
			exist[now]=1;
		}
		return;
	}
	
	int mid=(L+R)>>1;
	int L_son=now<<1, R_son=now<<1|1;
	if (x<=mid) {
		update(L_son, L, mid, x);
	}
	else {
		update(R_son, mid+1, R, x);
	}
	
	push_up(now);
}

int n, m;
int main() {
	scanf("%d %d", &n, &m);
	for (re int i=1; i<=n; i++) {
		scanf("%d %d", &T[i].a, &T[i].b);
		T[i].num=0; T[i].site=i;
	}
	
	for (re int i=n+1; i<=n+m; i++) {
		scanf("%d %d %d", &T[i].site, &T[i].a, &T[i].b);
		T[i].num=i-n;
	}
	
	sort(T+1, T+n+m+1, cmp);
	
	for (re int i=1; i<=n+m; i++) {
		if (T[i].num) qry[T[i].num]=i;
		else orig[T[i].site]=i;
	}
	
	build(1, 1, n+m);
	
	for (re int i=1; i<=m; i++) {
		update(1, 1, n+m, orig[T[qry[i]].site]);
		orig[T[qry[i]].site]=qry[i];
		update(1, 1, n+m, qry[i]);
		printf("%lld\n", b[1]);
	}
	
	return 0;
}
posted @ 2020-08-13 22:25  willbe233  阅读(93)  评论(0)    收藏  举报