题目
Description
小明的机器上运行着
n
n
n 个程序
P
1
,
P
2
,
…
,
P
n
P_1,P_2,…,P_n
P1,P2,…,Pn ,其中程序
P
i
P_i
Pi 占用着
a
i
a_i
ai 个单位的内存,仍需要
b
i
b_i
bi 个单位的内存这个程序才能结束。小明可以为程序
P
i
P_i
Pi 分配至少
b
i
b_i
bi 个单位的空闲内存,结束这个程序。当程序
P
i
P_i
Pi 结束的时候,它会把它之前占用的
a
i
a_i
ai 个单位的内存和分配的
b
i
b_i
bi 个单位的内存一起释放,而小明可以把这些内存回收回来,与原来的空闲内存组成新的空闲内存小明想知道,他机器上的空闲内存至少应该是多少个单位,他的所有程序才有可能全部运行完。除此之外,每经过一分钟,小明的机器上都有一个程序
P
j
P_j
Pj 发生改变,即
a
j
,
b
j
a_j,b_j
aj,bj 变成了
a
j
′
,
b
j
′
a'_j,b'_j
aj′,bj′。注意,同一个程序有可能会变化多次。你能帮小明计算,每次程序发生变化之后,系统上的空闲内存至少应该是多少个单位吗?
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
(
n
log
n
)
O(n\log n)
O(nlogn)。
#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;
}