1. 程式人生 > >URAL2014C之妙用線段樹

URAL2014C之妙用線段樹

題意: 題目中的小明呢,會賺錢和花錢,花錢的時候會先花掉自己賺的錢,再去花老爸的信用卡,要注意小明不會存錢進去。現在小明每賺一次錢或者花一次錢,都會寫一封信告訴老爸花了多少或者賺了多少,如果是用了老爸的信用卡,老爸就會記下來。但是收到信的順序和實際小明花錢的順序是不一樣的,現在要我們輸出每一次收到信老爸需要記錄的信用卡使用資訊。

有兩種線段樹可以做: 第一種: 對於當前的活動,只會影響到後面時間的負債,所以更新的話,就更新從當前時間到最後的這個區間。然後查詢的時候只要求出從當前時間到最後的一個最小值,然後和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+1
const 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+1
const 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+1
const 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;
}