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
- URAL2014C之妙用线段树
- 数据结构之线段树
- 数据结构之线段树
- 数据结构之线段树
- hdu1166之线段树
- hdu1754之线段树
- hdu1698之线段树
- poj3468之线段树
- 数据结构之线段树
- 线段树之Poj3264
- 线段树之hdu1166
- 数据结构之线段树
- 数据结构之线段树
- 数据结构之线段树
- 数据结构之线段树
- 线段树之 HDU4578Transformation
- 数据结构之线段树
- 数据结构之线段树
- 6. ZigZag Conversion
- poj 3671(暴力 枚举)
- python核心编程学习笔记-2016-08-13-06-元类
- Android Studio 编译不通过,报错“找不到org.apache.http。。。”
- AndroidListView显示item位置效果错误的问题
- URAL2014C之妙用线段树
- 【学习笔记】类的继承
- Java IO中几个主要类介绍和使用
- poj3252 Round Numbers(数位dp)
- Sencha Touch 解决 button tap事件 按下和弹起 两次响应
- 《Groovy程序设计》读书笔记之第二部分 面向Java开发者的Groovy(下)
- Android串口操作
- 【LightOJ - 1058】Parallelogram Counting
- codeforces-508C -鬼吹灯(巧妙模拟)