【洛谷P1816】忠诚——ST表做法
看了两个小时RMQ并位运算,对二进制勉勉强强有了个初步了解,不能说精通(可能今年CSP前都做不到精通),但是记熟板子做做题还是没有问题的
以下是正式题解,相信你看过了题目,我介绍的是ST表的做法(很简单)
如果你不想切出去也可以直接往下看(想看题解或代码往下翻翻)
(来源洛谷(截图)
分析
这题是真的完全没有掩饰的区间最值问题(RMQ),刚学的话拿来练板子还行(?),就是个模板题啦
这题就是板子改个大于小于的程度也搞不清为什么它是个绿题(模板题是黄题)
如果你学过ST表这题会又简单又好打,如果没有学过(就去学啊很重要的)
不会ST表打线段树当然也可以,但是线段树很长啊(发出蒟蒻的声音)
RMQ的模板在这,没学过可以去题解试试学一学,这里就不过多赘述
或者往下看我的代码注释(就当练习代码阅读能力)
代码
#include<cstdio> #include<iostream> #include<cmath> using namespace std; int n,m,a[100050],f[100050][100]; inline int read() { int x=0; char c=getchar(); while (c>'9'||c<'0') c=getchar(); do { x=x*10+c-48; c=getchar(); }while(c<='9'&&c>='0'); return x; } //快读,优化常数从我做起 inline void rmq() { for (int j=1; (1<<j)<=m; j++) for (int i=1; i+(1<<j)-1<=m; i++) f[i][j]=min(f[i][j-1],f[i+(1<<(j-1))][j-1]); }//核心预处理,运用DP和二进制 int main() { m=read(); n=read(); for (int i=1; i<=m; i++) { a[i]=read(); f[i][0]=a[i]; //初始化 } rmq(); int l,r; for (int i=1; i<=n; i++) { l=read(); r=read(); int k=floor(log(r-l+1)/log(2)); //2^k=r-l+1 printf("%d ",min(f[l][k],f[r-(1<<k)+1][k])); //这个地方用COUT会TLE!!凉凉 !!! } return 18751214;//本命生日防我自己偷窥 }
好的就是这些
惯例