URAL2014C之妙用线段树

本文介绍了一种利用线段树数据结构解决特定信用卡消费记录问题的方法。问题背景为小明赚取和花费资金,并使用父亲的信用卡进行消费,但消费记录顺序错乱。通过两种不同的线段树实现方案,解决了记录信用卡使用情况的问题。

题目传送门: 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+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;
}
智慧医药系统(smart-medicine)是一款采用SpringBoot架构构建的Java Web应用程序。其界面设计简洁而富有现代感,核心特色在于融合了当前前沿的生成式人工智能技术——具体接入了阿里云的通义千问大型语言模型,以此实现智能医疗咨询功能,从而增强系统的技术先进性与实用价值。该系统主要定位为医学知识查询与辅助学习平台,整体功能结构清晰、易于掌握,既适合编程初学者进行技术学习,也可作为院校课程设计或毕业项目的参考实现。 中医舌诊作为传统医学的重要诊断手段,依据舌象的颜色、形状及苔质等特征来辨析生理状况与病理变化。近年来,随着计算科学的进步,人工智能技术逐步渗透到这一传统领域,形成了跨学科的研究与应用方向。所述的中医舌诊系统正是这一方向的实践产物,它运用AI算法对舌象进行自动化分析。系统以SpringBoot为基础框架,该框架依托Java语言,致力于简化Spring应用程序的初始化与开发流程,其突出优势在于能高效构建独立、可投入生产的应用,尤其契合微服务架构与云原生环境,大幅降低了开发者在配置方面的负担。 系统中整合的通义千问大语言模型属于生成式人工智能范畴,通过海量数据训练获得模拟人类语言的能力,可在限定领域内生成连贯文本,为用户提供近似专业医生的交互式咨询。该技术的引入有助于提升诊断过程的自动化水平与结果一致性。 在设计与体验层面,本系统强调逻辑明晰与操作简便,旨在降低用户的学习门槛,尤其适合中医知识的入门教学。整体交互模式接近百科全书式查询,功能模块精炼聚焦,因而非常适用于教育场景,例如学术项目展示或毕业设计答辩。通过直观的实践界面,使用者能够更深入地理解中医舌诊的理论与方法。 此外,系统界面遵循简约大气的设计原则,兼顾视觉美感与交互流畅性,以提升用户的专注度与使用意愿。结合AI的数据处理能力,系统可实现对舌象特征的快速提取与实时分析,这不仅为传统诊断方法增添了客观量化维度,也拓展了中医知识传播的途径。借助网络平台,该系统能够突破地域限制,使更多用户便捷地获取专业化的中医健康参考,从而推动传统医学在现代社会的应用与普及。 资源来源于网络分享,仅用于学习交流使用,请勿用于商业,如有侵权请联系我删除!
【掺铒光纤放大器(EDFA)模型】掺铒光纤放大器(EDFA)分析模型的模拟研究(Matlab代码实现)内容概要:本文介绍了掺铒光纤放大器(EDFA)分析模型的模拟研究,并提供了基于Matlab的代码实现方案。通过对EDFA的工作原理、增益特性、噪声系数等关键性能指标进行数学建模与仿真分析,帮助研究人员深入理解其在光通信系统中的作用机制。文档还列举了多个相关科研方向的技术支持内容,涵盖智能优化算法、路径规划、无人机应用、通信与信号处理、电力系统管理等多个领域,展示了Matlab在科学研究与工程仿真中的广泛应用能力。此外,文中附带网盘链接,便于获取完整的代码资源与开发工具包。; 适合人群:具备一定光学通信或电子信息背景,熟悉Matlab编程,从事科研或工程仿真的研究生、高校教师及技术研发人员。; 使用场景及目标:①用于光通信系统中EDFA性能的理论分析与仿真验证;②支持科研人员快速构建和测试EDFA模型,提升研究效率;③为教学实验、毕业设计及学术论文复现提供可靠的技术参考与代码基础。; 阅读建议:建议读者结合光通信基础知识,按照文档结构逐步运行并调试Matlab代码,重点关注模型参数设置与仿真结果分析,同时可利用提供的网盘资源拓展学习其他相关课,深化对系统级仿真的理解。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值