我喜欢上了一个女孩,她的名字叫静静,我很想她。
题意:
Zhenya上大学时使用他爸给的信用卡,同时他也打工赚一些钱,他每次有收支都会给他爸爸寄一封信,内容是收入/支出多少钱,以及这次收支的时间。当Zhenya手头有自己赚的钱时,他会使用那些钱,其他时候他会使用信用卡。问题是邮政系统有问题,他爸爸收到信的时间并不按照收支发生的时间先后顺序,他爸爸想在每次收到一封信的时候根据当前信息判断信用卡欠费多少,所以有时会出现他爸第一天收到一封10号支出100的信,认为自己信用卡要还100,第二天又收到一封告诉他9号赚了100,这时他就认为自己信用卡不用还钱。
Zhenya爸爸收到了n封信,每次收到一封信都要求输出他认为自己欠费多少。
Input
Output
每次收入只会影响它之后的点,如果影响完所有它后面的点,仍为正,则没有作用。
一共n次操作,如果每次朴素更新,也要花O(N),TLE稳稳的。
可以用线段树来更新,通过递推关系来进行区间的更新。
将时间按分钟转化为点,建线段树,对线段树的每个点,维护sum表示该段的欠债,维护rec表示该段收入还完该段可以还(因为先后顺序导致的)的债以后,还可以还多少钱,然后就有
sum[i]=sum[ls]+min(0, sum[rs]+rec[ls]);
rec[i]=max(rec[ls]+rec[rs]+sum[rs],rec[rs]);
代码如下:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<cmath>
using namespace std;
#define mxp 610000
int ll[mxp<<2],rr[mxp<<2];
long long sum[mxp<<2],rec[mxp<<2];
const int maxx=365*24*60-1;
int day[]={0,31,28,31,30,31,30,31,31,30,31,30,31};
int n;
void init(){
int sum=0;
for(int i=0;i<=12;++i){
sum+=day[i];
day[i]=sum;
}
}
void build(int l,int r,int id){
ll[id]=l;
rr[id]=r;
sum[id]=rec[id]=0LL;
if(l==r) return;
int m=(l+r)>>1,ls=id<<1,rs=ls|1;
build(l,m,ls);
build(m+1,r,rs);
}
int convert(char a[],char b[]){
int tem=(a[3]-'0')*10+(a[4]-'0');
int t=(a[0]-'0')*10+(a[1]-'0');
tem=((day[tem-1]+t-1)*24+(b[0]-'0')*10+(b[1]-'0'))*60+((b[3]-'0')*10+(b[4]-'0'));
return tem;
}
void update(int loc,long long tgt,int id){
if(ll[id]==rr[id]){
sum[id]=tgt;
if(tgt>0){
sum[id]=0LL;
rec[id]=tgt;
}
return;
}
int m=(ll[id]+rr[id])>>1,ls=id<<1,rs=ls|1;
if(loc<=m) update(loc,tgt,ls);
else update(loc,tgt,rs);
sum[id]=sum[ls]+min(rec[ls]+sum[rs],0LL);
rec[id]=max(rec[ls]+sum[rs]+rec[rs],rec[rs]);
}
int main(){
while(scanf("%d",&n)!=EOF){
init();
build(0,maxx,1);
long long tem;
char a[10],b[10];
for(int i=0;i<n;++i){
scanf("%I64d%s%s",&tem,a,b);
int loc=convert(a,b);
update(loc,tem,1);
printf("%I64d\n",sum[1]);
}
}
return 0;
}