luogu P5097 [USACO2004OPEN]Cave Cows 2 洞穴里的牛之二

题面

在这里插入图片描述

分析

很简单,求区间[l,r]的最小值
线段树首选(只会线段树

code

#include<bits/stdc++.h>
using namespace std;
#define loop(i,start,end) for(int i=start;i<=end;i++)
#define clean(arry,num); memset(arry,num,sizeof(arry));
#define ll long long
ll n,q;
const int maxn=25010;
ll data[maxn];
ll minn[maxn<<2];
inline ll read()
{
   ll ans=0;char r=getchar();bool neg=false;
   while(r<'0'||r>'9'){if(r=='-')neg=true;r=getchar();}
   while(r>='0'&&r<='9'){ans=ans*10+r-'0';r=getchar();}
   return (neg)?-ans:ans;
}
void pushup(ll rt)
{
    minn[rt]=min(minn[rt<<1],minn[rt<<1|1]);
}
void buildtree(ll nl,ll nr,ll rt)
{
    if(nl==nr)
    {
        minn[rt]=data[nl];
        return;
    }
    ll m=(nr+nl)/2;
    buildtree(nl,m,rt<<1);
    buildtree(m+1,nr,rt<<1|1);
    pushup(rt);
}
ll query(ll l,ll r,ll nl,ll nr,ll rt)
{
    if(l<=nl&&nr<=r)
    {
        return minn[rt];
    }
    ll m=(nl+nr)/2;
    ll left=1e9+100;ll right=1e9+100;
    if(l<=m)left=min(left,query(l,r,nl,m,rt<<1));
    if(m<r)right=min(right,query(l,r,m+1,nr,rt<<1|1));
    return min(left,right);
}
int main()
{
    //freopen("datain.txt","r",stdin);
    n=read();q=read();
    loop(i,1,n)data[i]=read();
    buildtree(1,n,1);
    loop(i,1,q)
    {
        ll l,r;l=read();r=read();
        printf("%lld\n",query(l,r,1,n,1));
    }
    return 0;
}
/********************************************************************
   ID:Andrew_82
   LANG:C++
   PROG:s_tree
********************************************************************/

学到的东西

  • 万恶又万善的宏

注意到上面代码中有min函数,按照本蒟蒻以前的惯例,min函数从来都是用宏写
但当本蒟蒻信心满满的交上代码时,发现TLE了不少
以为算法错了,不断的改算法,提交,改算法,提交,无济于事
又去改精度,以为long long出问题(乱扯),又不断的改精度,提交,改精度,提交,还是无济于事
提交页面被本蒟蒻刷屏后,我一气之下cut掉了鬼畜的宏命令,然后的结果大家应该都知道了
在这里插入图片描述为什么呢????想当年各路巨佬用宏,类定义和函数模版AK虐全场时的风骚,怎么不复存在了呢????

看了Sleepp巨佬的资料后,蒟蒻恍然大悟
之前本蒟蒻的有关语句是这样写的

#define min(a,b) ((a>b)?b:a)
......
ll query(ll l,ll r,ll nl,ll nr,ll rt)
{
    if(l<=nl&&nr<=r)return minn[rt];
    ll m=(nl+nr)/2;
    ll left=1e9+100;ll right=1e9+100;
    if(l<=m)left=min(left,query(l,r,nl,m,rt<<1));
    if(m<r)right=min(right,query(l,r,m+1,nr,rt<<1|1));
    return min(left,right);
}

乍一看好像没问题,但是当把宏替换过来就很有趣了

#define min(a,b) ((a>b)?b:a)
......
ll query(ll l,ll r,ll nl,ll nr,ll rt)
{
    if(l<=nl&&nr<=r)return minn[rt];
    ll m=(nl+nr)/2;
    ll left=1e9+100;ll right=1e9+100;
    if(l<=m)left=((left>query(l,r,nl,m,rt<<1))?query(l,r,nl,m,rt<<1):left)
    if(m<r)right=((right>query(l,r,m+1,nr,rt<<1|1))?query(l,r,m+1,nr,rt<<1|1):right)
    return min(left,right);
}

原来只需要计算一次,宏定义下要计算两次!!!
不超时才怪
看来宏这个东西,不仅仅是优先级容易出错,函数调用上也容易出问题啊

但是为什么又要用宏呢?问过很多用宏的大佬,归纳出以下几点优势

  • 可以少打几个字~~~
  • 由于宏的本质是替换,不会进行函数的调用,故在某些情况下可以节省出函数调用的时间(本题除外 233······)
  • 看起来高大上
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

AndrewMe8211

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值