URAL2014C之妙用线段树

来源:互联网 发布:淘宝模特招聘是真的吗 编辑:程序博客网 时间:2024/06/17 22:47

题目传送门: http://acm.hust.edu.cn/vjudge/contest/128024#problem/C

题意: 题目中的小明呢,会赚钱和花钱,花钱的时候会先花掉自己赚的钱,再去花老爸的信用卡,要注意小明不会存钱进去。现在小明每赚一次钱或者花一次钱,都会写一封信告诉老爸花了多少或者赚了多少,如果是用了老爸的信用卡,老爸就会记下来。但是收到信的顺序和实际小明花钱的顺序是不一样的,现在要我们输出每一次收到信老爸需要记录的信用卡使用信息。

有两种线段树可以做: 第一种: 对于当前的活动,只会影响到后面时间的负债,所以更新的话,就更新从当前时间到最后的这个区间。然后查询的时候只要求出从当前时间到最后的一个最小值,然后和0比较就好,然后我们知道tree[1],一定会是最小的那个值。所以直接比较就好~

但是我的查询不知道为什么写丑了。。样例都过不了。。所以还是直接和tree[1]比较吧。。QAQ

代码:

#include <cstdio>#include <cstring>#include <algorithm>#include <iostream>#define lson root*2,l,mid#define rson root*2+1,mid+1,r#define ls root*2#define rs root*2+1const int MAXN=1000100;typedef long long ll;using namespace std;struct SGT{    ll tree[MAXN*4];    ll lazy[MAXN*4];    void pushup(int root)    {        tree[root]=min(tree[ls],tree[rs]);    }    void pushdown(int root,int l,int r)    {        tree[ls]+=lazy[root];        tree[rs]+=lazy[root];        lazy[ls]+=lazy[root];        lazy[rs]+=lazy[root];        lazy[root]=0;    }    void update(int root,int l,int r,int ql,int qr,ll x)    {           if(ql<=l&&r<=qr)        {            tree[root]+=x;            lazy[root]+=x;            return ;        }        int mid=(l+r)>>1;        pushdown(root,l,r);        if(mid>=ql)        {            update(lson,ql,qr,x);        }        if(mid<qr)        {            update(rson,ql,qr,x);        }        pushup(root);    }};SGT sgt;int main (void){    int t;    cin>>t;    while(t--)    {        int date,month,hour,mi;        ll mon;        scanf("%lld %d.%d %d:%d",&mon,&date,&month,&hour,&mi);        int po=(month-1)*31*24*60+date*24*60+hour*60+mi;        //printf("po=%d\n",po);        sgt.update(1,1,MAXN,po,MAXN,mon);        printf("%lld\n",sgt.tree[1]>0?0:sgt.tree[1]);        //printf("%lld\n",sgt.tree[1]>0?0:sgt.query(1,1,MAXN,1,po));    }    return 0;}

第二种:我们构造两棵线段树,对于第一棵,我们来存当前手上还有多少钱。(为了方便,我叫他现金树)

对于第二棵,我们来存信用卡花了多少钱。(为了方便,我叫他欠债树)

然后我们在pushup这里干活。

又由于我们是按照时间来建树的,所以:

如果现金树的左儿子比欠债树的右儿子要大,就说明我们能用钱抵消掉信用卡的债。 于是就有这样的pushup:

tree2[root]=tree2[ls];tree1[root]=tree1[ls]+tree1[rs]-tree2[rs];

否则,我们就只能用现金树的左儿子来抵消掉欠债树右儿子的一部分。 于是就有这样的pushup:

tree1[root]=tree1[rs];tree2[root]=tree2[ls]+tree2[rs]-tree1[ls];

要注意的是现金树只有左儿子才能还债。

代码:

#include <cstdio>#include <cstring>#include <algorithm>#include <iostream>#define lson root*2,l,mid#define rson root*2+1,mid+1,r#define ls root*2#define rs root*2+1const int MAXN=1000100;typedef long long ll;using namespace std;struct SGT{    ll tree1[MAXN*4];    ll tree2[MAXN*4];    void pushup(int root)    {        if(tree1[ls]>=tree2[rs])        {                       tree2[root]=tree2[ls];            tree1[root]=tree1[ls]+tree1[rs]-tree2[rs];        }        else        {            tree1[root]=tree1[rs];            tree2[root]=tree2[ls]+tree2[rs]-tree1[ls];        }    }    void update(int root,int l,int r,int p,ll x)    {        if(l==r)        {            if(x>0)            {                tree1[root]=x;//手上有多少钱            }            else            {                tree2[root]=-x;//信用卡用了多少            }            return ;        }        int mid=(l+r)>>1;        if(mid>=p)        {            update(lson,p,x);        }        else        {            update(rson,p,x);        }        pushup(root);    }};SGT sgt;int main (void){    int t;    cin>>t;    while(t--)    {        int date,month,hour,mi;        ll mon;        scanf("%I64d %d.%d %d:%d",&mon,&date,&month,&hour,&mi);        int po=(month-1)*31*24*60+date*24*60+hour*60+mi;        //printf("po=%d\n",po);        sgt.update(1,1,MAXN,po,mon);        printf("%I64d\n",-sgt.tree2[1]);    }    return 0;}

所以大牛们能告诉我一下为什么下面这样查询是不对的呢。。QAQ

#include <cstdio>#include <cstring>#include <algorithm>#include <iostream>#define lson root*2,l,mid#define rson root*2+1,mid+1,r#define ls root*2#define rs root*2+1const int MAXN=1000100;typedef long long ll;using namespace std;struct SGT{    ll tree[MAXN*4];    ll lazy[MAXN*4];    void pushup(int root)    {        tree[root]=min(tree[ls],tree[rs]);    }    void pushdown(int root,int l,int r)    {        tree[ls]+=lazy[root];        tree[rs]+=lazy[root];        lazy[ls]+=lazy[root];        lazy[rs]+=lazy[root];        lazy[root]=0;    }    void update(int root,int l,int r,int ql,int qr,ll x)    {           if(ql<=l&&r<=qr)        {            tree[root]+=x;            lazy[root]+=x;            return ;        }        int mid=(l+r)>>1;        pushdown(root,l,r);        if(mid>=ql)        {            update(lson,ql,qr,x);        }        if(mid<qr)        {            update(rson,ql,qr,x);        }        pushup(root);    }    ll query(int root,int l,int r,int ql,int qr)    {        if(ql<=l&&r<=qr)        {            return tree[root];        }        pushdown(root,l,r);        int mid=(l+r)>>1;        ll ans=0xffffffff;        if(mid>=ql)        {            ans=min(ans,query(lson,ql,qr));        }        if(mid<qr)        {            ans=min(ans,query(rson,ql,qr));        }        return ans;    }};SGT sgt;int main (void){    int t;    cin>>t;    while(t--)    {        int date,month,hour,mi;        ll mon;        scanf("%lld %d.%d %d:%d",&mon,&date,&month,&hour,&mi);        int po=(month-1)*31*24*60+date*24*60+hour*60+mi;        //printf("po=%d\n",po);        sgt.update(1,1,MAXN,po,MAXN,mon);        //printf("%I64d\n",sgt.tree[1]>0?0:sgt.tree[1]);        printf("%lld\n",sgt.query(1,1,MAXN,po,MAXN)>0?0:sgt.query(1,1,MAXN,1,MAXN));    }    return 0;}
0 0
原创粉丝点击