HDU多校4 - 6989 Didn‘t I Say to Make My Abilities Average in the Next Life?!(单调栈)
題目鏈接:點擊查看
題目大意:給出一個長度為 nnn 的序列,再給出 mmm 次詢問,每次詢問給出一個區間 [l,r][l,r][l,r],要求輸出區間 [l,r][l,r][l,r] 內 “平均值” 的期望。區間 [l,r][l,r][l,r] 的 “平均值”,是等概率的選擇一個子區間 [L,R][L,R][L,R],滿足 l≤L≤R≤rl\le L\le R \le rl≤L≤R≤r,“平均值” = ([L,R][L,R][L,R]內的最大值+[L,R][L,R][L,R]內的最小值)/2
題目分析:對于每次詢問來說,因為選擇每個子區間的概率都是相等的,所以定義一下變量 sum_maxsum\_maxsum_max 為 [l,r][l,r][l,r] 內所有子區間的最大值之和,sum_minsum\_minsum_min 為 [l,r][l,r][l,r] 內所有子區間的最小值之和。又因為長度為 lenlenlen 的區間有 len?(len+1)2\frac{len*(len+1)}{2}2len?(len+1)? 個子區間,所以對于每次詢問的答案就是:sum_max+sum_min2?len?(len+1)2=sum_max+sum_minlen?(len+1)\frac{sum\_max+sum\_min}{2*\frac{len*(len+1)}{2}}=\frac{sum\_max+sum\_min}{len*(len+1)}2?2len?(len+1)?sum_max+sum_min?=len?(len+1)sum_max+sum_min?
所以本題的難點就是如何快速求解 sum_minsum\_minsum_min 和 sum_maxsum\_maxsum_max 了
所以套上典中典的模板就可以通過了:洛谷 - P3246 [HNOI2016]序列
需要注意的是,連乘有可能爆long long,需要及時取模
代碼:
// Problem: Didn't I Say to Make My Abilities Average in the Next Life?! // Contest: Virtual Judge - HDU // URL: https://vjudge.net/problem/HDU-6989 // Memory Limit: 524 MB // Time Limit: 4000 ms // // Powered by CP Editor (https://cpeditor.org)// #pragma GCC optimize(2) // #pragma GCC optimize("Ofast","inline","-ffast-math") // #pragma GCC target("avx,sse2,sse3,sse4,mmx") #include<iostream> #include<cstdio> #include<string> #include<ctime> #include<cmath> #include<cstring> #include<algorithm> #include<stack> #include<climits> #include<queue> #include<map> #include<set> #include<sstream> #include<cassert> #include<bitset> #include<list> #include<unordered_map> #define lowbit(x) (x&-x) using namespace std; typedef long long LL; typedef unsigned long long ull; template<typename T> inline void read(T &x) {T f=1;x=0;char ch=getchar();while(0==isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}while(0!=isdigit(ch)) x=(x<<1)+(x<<3)+ch-'0',ch=getchar();x*=f; } template<typename T> inline void write(T x) {if(x<0){x=~(x-1);putchar('-');}if(x>9)write(x/10);putchar(x%10+'0'); } const int inf=0x3f3f3f3f; const int N=2e5+100; const int mod=1e9+7; int n,m,a[N],l[N],r[N],mmin[N][20],mmax[N][20],Log[N]; LL fl[N][2],fr[N][2],gl[N][2],gr[N][2]; int cmp1(int x,int y) {return a[x]<a[y]?x:y; } int cmp2(int x,int y) {return a[x]>a[y]?x:y; } int st_min(int l,int r) {int k=Log[r-l+1];return cmp1(mmin[l][k],mmin[r-(1<<k)+1][k]); } int st_max(int l,int r) {int k=Log[r-l+1];return cmp2(mmax[l][k],mmax[r-(1<<k)+1][k]); } void init_min() {//單調棧stack<int>st;for(int i=1;i<=n;i++) {while(st.size()&&a[st.top()]>a[i]) st.pop();if(st.empty()) l[i]=0;else l[i]=st.top();st.push(i);}while(st.size()) st.pop();for(int i=n;i>=1;i--) {while(st.size()&&a[st.top()]>a[i]) st.pop();if(st.empty()) r[i]=n+1;else r[i]=st.top();st.push(i);}//RMQfor(int i=1;i<=n;i++)mmin[i][0]=i,Log[i]=log2(i);for(int i=1;i<20;i++)for(int j=1;j+(1<<i)-1<=n;j++)mmin[j][i]=cmp1(mmin[j][i-1],mmin[j+(1<<(i-1))][i-1]);//dpfor(int i=1;i<=n;i++) fr[i][0]=(fr[l[i]][0]+1LL*(i-l[i])*a[i])%mod,gr[i][0]=(gr[i-1][0]+fr[i][0])%mod;for(int i=n;i>=1;i--) fl[i][0]=(fl[r[i]][0]+1LL*(r[i]-i)*a[i])%mod,gl[i][0]=(gl[i+1][0]+fl[i][0])%mod; } void init_max() {//單調棧stack<int>st;for(int i=1;i<=n;i++) {while(st.size()&&a[st.top()]<a[i]) st.pop();if(st.empty()) l[i]=0;else l[i]=st.top();st.push(i);}while(st.size()) st.pop();for(int i=n;i>=1;i--) {while(st.size()&&a[st.top()]<a[i]) st.pop();if(st.empty()) r[i]=n+1;else r[i]=st.top();st.push(i);}//RMQfor(int i=1;i<=n;i++)mmax[i][0]=i,Log[i]=log2(i);for(int i=1;i<20;i++)for(int j=1;j+(1<<i)-1<=n;j++)mmax[j][i]=cmp2(mmax[j][i-1],mmax[j+(1<<(i-1))][i-1]);//dpfor(int i=1;i<=n;i++) fr[i][1]=(fr[l[i]][1]+1LL*(i-l[i])*a[i])%mod,gr[i][1]=(gr[i-1][1]+fr[i][1])%mod;for(int i=n;i>=1;i--) fl[i][1]=(fl[r[i]][1]+1LL*(r[i]-i)*a[i])%mod,gl[i][1]=(gl[i+1][1]+fl[i][1])%mod; } LL ask_max(int l,int r) {int p=st_max(l,r);return ((1LL*(p-l+1)*(r-p+1)%mod*a[p]+gr[r][1]-gr[p][1]-fr[p][1]*(r-p)+gl[l][1]-gl[p][1]-fl[p][1]*(p-l))%mod+mod)%mod; } LL ask_min(int l,int r) {int p=st_min(l,r);return ((1LL*(p-l+1)*(r-p+1)%mod*a[p]+gr[r][0]-gr[p][0]-fr[p][0]*(r-p)+gl[l][0]-gl[p][0]-fl[p][0]*(p-l))%mod+mod)%mod; } LL q_pow(LL a,LL b) {LL ans=1;while(b) {if(b&1) {ans=ans*a%mod;}a=a*a%mod;b>>=1;}return ans; } LL inverse(LL x) {return q_pow(x%mod,mod-2); } int main() { #ifndef ONLINE_JUDGE // freopen("data.in.txt","r",stdin); // freopen("data.out.txt","w",stdout); #endif // ios::sync_with_stdio(false);int w;cin>>w;while(w--) {read(n),read(m);for(int i=1;i<=n;i++) {read(a[i]);}init_max(),init_min();while(m--) {int l,r;read(l),read(r);printf("%lld\n",(ask_max(l,r)+ask_min(l,r))*inverse(1LL*(r-l+1)*(r-l+2))%mod);}}return 0; }總結
以上是生活随笔為你收集整理的HDU多校4 - 6989 Didn‘t I Say to Make My Abilities Average in the Next Life?!(单调栈)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: HDU - 7008 水题(打表)
- 下一篇: CodeForces - 1549F1