URAL2014C之妙用線段樹
阿新 • • 發佈:2018-12-24
題意: 題目中的小明呢,會賺錢和花錢,花錢的時候會先花掉自己賺的錢,再去花老爸的信用卡,要注意小明不會存錢進去。現在小明每賺一次錢或者花一次錢,都會寫一封信告訴老爸花了多少或者賺了多少,如果是用了老爸的信用卡,老爸就會記下來。但是收到信的順序和實際小明花錢的順序是不一樣的,現在要我們輸出每一次收到信老爸需要記錄的信用卡使用資訊。
有兩種線段樹可以做: 第一種: 對於當前的活動,只會影響到後面時間的負債,所以更新的話,就更新從當前時間到最後的這個區間。然後查詢的時候只要求出從當前時間到最後的一個最小值,然後和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;
}