[hdu6989]Didn't I Say to Make My Abilities Average in the Next Life?!
显然问题即求$\frac{\sum_{x\le l\le r\le y}(\max_{l\le i\le r}a_{i}+\min_{l\le i\le r}a_{i})}{(y-x+2)(y-x+1)}$
分母显然是常数,分子中$\max$和$\min$是类似地,不妨仅考虑$\sum_{x\le l\le r\le y}\max_{l\le i\le r}a_{i}$
将询问离线,不断增大右端点$r$,并维护$ans_{i}=\sum_{r'=i}^{r}\max_{i\le j\le r'}a_{j}$,那么即对$ans_{i}$区间求和
将$ans_{i}$写作$r\cdot max_{i}-sum_{i}$的形式(其中$max_{i}=\max_{i\le j\le r}a_{j}$),显然可以对两者分别求和
下面,考虑从$r-1$变为$r$对$(max_{i},sum_{i})$的影响:
维护一个单调栈(从栈底到栈顶单调递减),假设弹出栈顶元素$x$,且下一个元素为$y$(若栈为空则$y=0$),那么即对区间$(y,x]$的$max_{i}$增加$a_{r}-a_{x}$,$sum_{i}$增加$(r-1)(a_{r}-a_{x})$
另外还要维护$r$的答案,即令$(max_{r},sum_{r})=(a_{r},(r-1)a_{r})$
即要支持区间加和区间查询,使用线段树即可,复杂度为$o(n\log n)$,可以通过
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define N 200005 4 #define mod 1000000007 5 #define ll long long 6 #define pii pair<int,int> 7 #define mp make_pair 8 #define fi first 9 #define se second 10 #define L (k<<1) 11 #define R (L+1) 12 #define mid (l+r>>1) 13 struct Data{ 14 int l,r,id; 15 bool operator < (const Data &k)const{ 16 return r<k.r; 17 } 18 }q[N]; 19 int t,n,m,inv[N],a[N],mn[N],mx[N],ans[N]; 20 pii tag[N<<2],f[N<<2]; 21 pii merge(pii x,pii y){ 22 return mp((x.fi+y.fi)%mod,(x.se+y.se)%mod); 23 } 24 void upd(int k,int l,int r,pii o){ 25 int len=r-l+1; 26 tag[k]=merge(tag[k],o); 27 f[k]=merge(f[k],mp((ll)len*o.fi%mod,(ll)len*o.se%mod)); 28 } 29 void down(int k,int l,int r){ 30 upd(L,l,mid,tag[k]); 31 upd(R,mid+1,r,tag[k]); 32 tag[k]=mp(0,0); 33 } 34 void build(int k,int l,int r){ 35 f[k]=mp(0,0); 36 if (l==r)return; 37 build(L,l,mid); 38 build(R,mid+1,r); 39 } 40 void update(int k,int l,int r,int x,int y,pii z){ 41 if ((l>y)||(x>r))return; 42 if ((x<=l)&&(r<=y)){ 43 upd(k,l,r,z); 44 return; 45 } 46 down(k,l,r); 47 update(L,l,mid,x,y,z); 48 update(R,mid+1,r,x,y,z); 49 f[k]=merge(f[L],f[R]); 50 } 51 pii query(int k,int l,int r,int x,int y){ 52 if ((l>y)||(x>r))return mp(0,0); 53 if ((x<=l)&&(r<=y))return f[k]; 54 down(k,l,r); 55 return merge(query(L,l,mid,x,y),query(R,mid+1,r,x,y)); 56 } 57 int main(){ 58 inv[0]=inv[1]=1; 59 for(int i=2;i<N;i++)inv[i]=(ll)(mod-mod/i)*inv[mod%i]%mod; 60 scanf("%d",&t); 61 while (t--){ 62 scanf("%d%d",&n,&m); 63 for(int i=1;i<=n;i++)scanf("%d",&a[i]); 64 for(int i=1;i<=m;i++){ 65 scanf("%d%d",&q[i].l,&q[i].r); 66 q[i].id=i; 67 } 68 sort(q+1,q+m+1); 69 mn[0]=mx[0]=0; 70 memset(tag,0,sizeof(tag)); 71 memset(f,0,sizeof(f)); 72 for(int i=1,j=1;i<=n;i++){ 73 update(1,1,n,i,i,mp(2*a[i]%mod,(ll)2*(i-1)*a[i]%mod)); 74 while ((mx[0])&&(a[mx[mx[0]]]<a[i])){ 75 int x=mx[mx[0]],y=mx[--mx[0]]; 76 update(1,1,n,y+1,x,mp((a[i]-a[x]+mod)%mod,(ll)(i-1)*(a[i]-a[x]+mod)%mod)); 77 } 78 while ((mn[0])&&(a[mn[mn[0]]]>a[i])){ 79 int x=mn[mn[0]],y=mn[--mn[0]]; 80 update(1,1,n,y+1,x,mp((a[i]-a[x]+mod)%mod,(ll)(i-1)*(a[i]-a[x]+mod)%mod)); 81 } 82 mx[++mx[0]]=mn[++mn[0]]=i; 83 while ((j<=m)&&(q[j].r==i)){ 84 pii o=query(1,1,n,q[j].l,i); 85 ans[q[j].id]=((ll)i*o.fi-o.se+mod)%mod*inv[i-q[j].l+2]%mod*inv[i-q[j].l+1]%mod; 86 j++; 87 } 88 } 89 for(int i=1;i<=m;i++)printf("%d\n",ans[i]); 90 } 91 return 0; 92 }