题目描述
线段树水题专项赛:Portal
Mirko的披萨店在镇上很受欢迎,每个人都把披萨作为午餐。Mirko提供外送服务,他的送货速度非常快,所以送货的时间可以忽略不计。镇上每个人都有自己最喜欢的口味,所以,Mirko给每个人做的披萨需要不同的时间。他只有一个小烤炉,每次只能烤一个披萨。如果他给某个人的披萨早于那个人的午餐时间k个时间单位,那么他可以收到k单位的小费,反之,如果晚于客户的午餐时间k个时间单位,那么他将损失k单位的钱。所以,Mirko需要提前安排好每个披萨制作的次序,以保证他的小费尽量多。每个客户的午餐时间是确定的,他的披萨需要花多少时间做好也是确定的。但是,可能客户会有所改变,一旦改变,那么mirko可能需要调整他的计划。Mirko从时刻0开始制作披萨,对于每一次改变,请输出现在小费能达到的最大值。
人数
n≤200000
,任何时间
≤100000
题目解析
我们可以先贪心一下,因为答案为
午餐时间之和−制作总时间
,即我们要让制作时间最小,又因为第
i
个制作的披萨代价是
初始的小费是可以直接排序算出来的,那怎么算修改后的呢?
对于每一次修改,我们可以看做删除一个订单再加入一个订单,删除的收益为
w×(n−rankw+1)+sumrankw
,
rankw
是
w
在原定单中的排名,
(mdzz,我一来咋想Splay去了呢,一定是我最近Splay写多了,跑得shi慢)
代码
#include<iostream>
#include<cstring>
#include<cstdio>
#include<set>
#include<vector>
#include<algorithm>
#include<cstdlib>
#include<queue>
using namespace std;
#define MAXN 200000
#define MAXM 100000
#define INF 0x3f3f3f3f
typedef long long int LL;
template<class T>
void Read(T &x){
x=0;char c=getchar();bool flag=0;
while(c<'0'||'9'<c){if(c=='-')flag=1;c=getchar();}
while('0'<=c&&c<='9'){x=x*10+c-'0';c=getchar();}
if(flag)x=-x;
}
int n,m;
int lim[MAXN+10],t[MAXN+10];
int tmp[MAXN+10];
int sz[MAXM+10];
LL sum[MAXM+10];
int lowbit(int &x){return x&-x;}
void add(int x,int k,int val){
while(x<=MAXM){
sz[x]+=k;
sum[x]+=1ll*k*val;
x+=lowbit(x);
}
}
int queryrank(int x){
int rn=0;
while(x>0){
rn+=sz[x];
x-=lowbit(x);
}
return rn;
}
LL querysum(int x){
LL rn=0;
while(x>0){
rn+=sum[x];
x-=lowbit(x);
}
return rn;
}
int main(){
//freopen("pizza.in","r",stdin);
//freopen("pizza.out","w",stdout);
Read(n),Read(m);
for(int i=1;i<=n;++i){
Read(lim[i]);
Read(t[i]);
tmp[i]=t[i];
}
sort(tmp+1,tmp+n+1);
LL ans=0;
for(int i=1;i<=n;++i){
ans+=lim[i];
ans-=1ll*tmp[i]*(n-i+1);
}
for(int i=1;i<=n;++i)
add(t[i],1,t[i]);
printf("%lld\n",ans);
int id,new_lim,new_t;
for(int i=1;i<=m;++i){
Read(id),Read(new_lim),Read(new_t);
ans-=lim[id];
ans+=(lim[id]=new_lim);
ans+=1ll*t[id]*(n-(queryrank(t[id]-1)+1)+1);
ans+=querysum(t[id]-1);
add(t[id],-1,t[id]);
t[id]=new_t;
add(t[id],1,t[id]);
ans-=1ll*t[id]*(n-(queryrank(t[id]-1)+1)+1);
ans-=querysum(t[id]-1);
printf("%lld\n",ans);
}
}