题面
分析
很简单,求区间[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······)
看起来高大上