HDU - 5875 Function(单调栈)
題目鏈接:點擊查看
題目大意:給出一段連續數列,在給出m個詢問,要求按照給出的函數查詢得到結果
題目分析:第一眼一看題目會覺得是個遞歸題目,但是盲目遞歸肯定會TLE,所以我們要分析這個題目到底要干什么,這個題目其實就是問在閉區間[l,r]內,一開始數字為a[l],然后依次對a[l+1]到a[r]取模,即連續取模,分析了半天發現也沒有什么性質,但是卻發現了一個小技巧,就是當一個數取模時,如果模比這個數要大的話,那對這個數是沒有影響的,只有當模小于等于這個數的時候取模才是有意義的,所以我們可以將連續取模優化為每次找到一個比當前結果要小于等于的數再進行取模,類似于跳著取模,這樣就能將時間復雜度大大降低,所以我們可以用線段樹來存儲區間內的最小值,這樣在查詢的時候就可以優先查詢左區間,這樣就可以同時滿足“第一個”和“比當前數字小”這兩個條件了。不過我線段樹還是菜啊,自己埋著頭調了一個小時也沒調好那個查詢函數,總是有點小bug,轉念一想,想起來好像就是要查找右邊第一個小的數字,那么能不能用單調棧莽一下,因為單調棧的主要用處就是用o的時間復雜度來存儲左邊或右邊第一個比當前數字大或小的位置,有了這樣一個剪枝,雖然最后每次取模的次數相對于線段樹來說會增多,但相對于暴力比較來說還是快了不少呢,畢竟也是跳著取模。。而且最后事實也說明了,數據沒有那種特別惡心的,單調棧跑出來的還是比線段樹快啊,因為單調棧的時間復雜度是n,此后查詢時間復雜度就變為了1,這樣在遍歷一遍每個區間,總的時間復雜度稍大于n+m吧,因為每次查詢雖然是要跳著查詢,但還是會找很多次。。但線段樹的話,建樹nlogn,每次查詢也是logn,最壞的查詢也是logn*logn,所以時間復雜度是nlogn+nlogn*logn,搭眼一看,一般數據來說肯定是單調棧更快一點,但是特殊數據可能會卡。。不過謝天謝地這個題目沒有出那種惡心人的數據。
直接上代碼了,單調棧好久沒用了,從網上復制的板子:
#include<iostream> #include<cstdio> #include<string> #include<cstring> #include<algorithm> #include<stack> #include<queue> #include<map> #include<cmath> #include<set> #include<sstream> using namespace std;typedef long long LL;const int inf=0x3f3f3f3f;const int N=1e5+100;int a[N];int id[N];int main() { // freopen("input.txt","r",stdin)int w;cin>>w;while(w--){int n,m;scanf("%d",&n);for(int i=1;i<=n;i++)scanf("%d",a+i);stack<int>s;for(int i=n;i>=1;i--){while(!s.empty()&&a[s.top()]>a[i])//單調棧{s.pop();}if(s.empty())id[i]=-1;elseid[i]=s.top();s.push(i);}scanf("%d",&m);while(m--){int x,y;scanf("%d%d",&x,&y);if(x==y){printf("%d\n",a[x]);}else{int ans=a[x];while(1){int pos=id[x];if(pos==-1||pos>y)break;ans%=a[pos];x=pos;}printf("%d\n",ans);}}}return 0; }?
總結
以上是生活随笔為你收集整理的HDU - 5875 Function(单调栈)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: CodeForces - 1036B D
- 下一篇: HDU - 5874 Friends a