Gym 100507C Zhenya moves from parents (线段树)

Zhenya moves from parents

题目链接:

http://acm.hust.edu.cn/vjudge/contest/126546#problem/C

Description

Zhenya moved from his parents’ home to study in other city. He didn’t take any cash with him, he only took his father’s credit card with zero balance on it. Zhenya succeeds in studies at the University and sometimes makes a little money on the side as a Maths tutor. As he makes his own money he spends only it, and when it is over he uses the credit card. Every time he gets or spends money, he sends a letter to his father, where he puts the following two things. 1. The date when it took place 2. The sum of earned or spent money Every time receiving a letter from Zhenya, his father calculates the debt on the credit card at the moment. But here a problem arises. The point is that Russian Post delivers letters in an order different to the one they were sent in. For example, in the first Zhenya’s letter the father read that on September 10 Zhenya spent one thousand rubles. He thought that his son had used the credit card, and now the debt is one thousand rubles. However the next day came a letter with the information that on September 9 Zhenya earned five hundred rubles. It means that half of the money he spent on September 10 was his own, and the debt on the credit card is just five hundred rubles. Help Zhenya’s father with his account management.

Input

The first line contains an integer 𝑛 which is the number of Zhenya’s letters (1 ≤ 𝑛 ≤ 100 000). These letters are listed in the next 𝑛 lines. Description of each letter consists of the amount of money Zhenya spent or earned (in the form -c or +c accordingly, where c is an integer, 1 ≤ 𝑐 ≤ 50 000) followed by both date and time when it took place (in the form of dd.MM hh:mm). All dates belong to the same year, which is not leap (i. e. there are 365 days in it). Any two letters contain either different dates or different time. The letters are listed in the order the father received them.

Output

After each received letter output what Zhenya’s father thinks the amount of the debt on the credit card is.

Example

test answer 5 -1000 10.09 21:00 +500 09.09 14:00 +1000 02.09 00:00 -1000 17.09 21:00 +500 18.09 13:00 -1000 -500 0 -500 -500
##题意: Zhenya有一张信用卡,每当消费时手上有现金都优先花掉现金,否则就透支信用卡. 他也会赚钱,赚得的钱都是现金并且不会用来还信用卡. 每次消费和赚钱他都会写信给他爸爸,但是信的邮寄顺序和消费时间顺序不一致. 父亲每收到一封信都要推断此时信用卡的透支状况.
##题解: 由于赚到的钱不会还卡,那么问题的核心是如何把现金和信用卡统一起来: 考虑赚到的钱,虽然不会还卡,但是在后面的消费中会优先使用现金. 所以赚/花的钱只会影响影响后续的行为,而不会影响之前欠款.
对时间离散化,用线段树维护区间最小值. 每次赚/花钱时更新当前时间点以及以后的时间点. 每次查询整个过程中的最小值,即最大欠款. (最小值大于0时输出0,即无透支)

##代码: ``` cpp #include #include #include #include #include #include #include #include #include #define LL long long #define eps 1e-8 #define maxn 101000 #define mod 100000007 #define inf 0x3f3f3f3f #define mid(a,b) ((a+b)>>1) #define IN freopen("in.txt","r",stdin); using namespace std;

struct Tree
{
int left,right;
LL lazy,mini;
}tree[maxn<<2]; /四倍大小/

/递归建树/
void build(int i,int left,int right)
{
tree[i].left=left;
tree[i].right=right;
tree[i].lazy=0;

if(left==right){
    tree[i].mini = 0;
    return ;
}

int mid=mid(left,right);

build(i<<1,left,mid);
build(i<<1|1,mid+1,right);

tree[i].mini = min(tree[i<<1].mini, tree[i<<1|1].mini);

}

/区间修改,标记下传:每当访问到当前结点的子节点时,下传标记/
void pushdown(int i)
{
if(tree[i].lazy){
tree[i<<1].lazy+=tree[i].lazy;
tree[i<<1|1].lazy+=tree[i].lazy;
tree[i<<1].mini+=tree[i].lazy;
tree[i<<1|1].mini+=tree[i].lazy;
tree[i].lazy=0; /下传后清零/
}
}

/区间修改,d为改变量/
void update(int i,int left,int right,LL d)
{
if(tree[i].leftleft&&tree[i].rightright)
{
tree[i].mini += d;
tree[i].lazy += d;
return ;
}

pushdown(i);

int mid=mid(tree[i].left,tree[i].right);

if(right<=mid) update(i<<1,left,right,d);
else if(left>mid) update(i<<1|1,left,right,d);
else
{
    update(i<<1,left,mid,d);
    update(i<<1|1,mid+1,right,d);
}

tree[i].mini = min(tree[i<<1].mini, tree[i<<1|1].mini);

}

/区间结果查询/
LL query(int i,int left,int right)
{
if(tree[i].leftleft&&tree[i].rightright)
return tree[i].mini;

pushdown(i);

int mid=mid(tree[i].left,tree[i].right);

if(right<=mid) return query(i<<1,left,right);
else if(left>mid) return query(i<<1|1,left,right);
else return min(query(i<<1,left,mid),query(i<<1|1,mid+1,right));

}

int n;
int monthly[] = {0,31,28,31,30,31,30,31,31,30,31,30,31};
struct node {
LL money;
int time;
}rec[maxn];
int t[maxn];

int main(int argc, char const *argv[])
{
//IN;

for(int i=1; i<=12; i++)
    monthly[i] += monthly[i-1];

while(scanf("%d", &n) != EOF)
{
    for(int i=1; i<=n; i++) {
        scanf("%I64d", &rec[i].money);
        int a,b,c,d;
        scanf("%d.%d %d:%d", &a,&b,&c,&d);
        rec[i].time = (monthly[b-1] + a)*24*60 + c*60 + d;
        t[i] = rec[i].time;
    }
    sort(t+1, t+1+n);

    map<int,int> mymap; mymap.clear();
    for(int i=1; i<=n; i++) {
        mymap.insert(make_pair(t[i], i));
    }

    build(1, 1, n);
    for(int i=1; i<=n; i++) {
        int pos = mymap[rec[i].time];
        update(1, pos, n, rec[i].money);
        LL ans = min(query(1, 1, n), 0LL);
        printf("%I64d\n", ans);
    }
}

return 0;

}

posted @ 2016-08-08 19:21  Sunshine_tcf  阅读(433)  评论(0编辑  收藏  举报