傳送門
文章目錄
題意:
思路:
考慮將貢獻分開來算,先計算最大值,再算個最小值,之后答案就是((max+min)/2)/(len?(len+1)/2)((max+min)/2)/(len*(len+1)/2)((max+min)/2)/(len?(len+1)/2)。
這是一個原題,直接封裝兩個結構體跑兩次答案即可。
在線做法且復雜度O(nlogn)O(nlogn)O(nlogn),吊打標程 。
當然還有線段樹 + 單調棧的寫法,目前沒看懂,看懂再補。
#include<cstdio>
#include<iostream>
#include<string>
#include<cstring>
#include<map>
#include<cmath>
#include<cctype>
#include<vector>
#include<set>
#include<queue>
#include<algorithm>
#include<sstream>
#include<ctime>
#include<cstdlib>
#include<random>
#include<cassert>
#define X first
#define Y second
#define L (u<<1)
#define R (u<<1|1)
#define pb push_back
#define mk make_pair
#define Mid ((tr[u].l+tr[u].r)>>1)
#define Len(u) (tr[u].r-tr[u].l+1)
#define random(a,b) ((a)+rand()%((b)-(a)+1))
#define db puts("---")
using namespace std
;
void rd_ac() { freopen("d://dp//data.txt","r",stdin); freopen("d://dp//AC.txt","w",stdout); }
typedef long long LL
;
typedef unsigned long long ULL
;
typedef pair
<int,int> PII
;const int N
=400010,mod
=1e9+7,INF
=0x3f3f3f3f;
const double eps
=1e-6;int n
,m
;
int a
[N
];
int stk
[N
],top
;
LL suf
[N
],pre
[N
];
LL psum
[N
],ssum
[N
];
int len
[N
];
PII q
[N
];
LL all
[N
];
int f
[N
][25];struct Node1 {void rmq_init(){memset(f
,0,sizeof(f
));for(int i
=1;i
<=n
;i
++) f
[i
][0]=i
;int t
=log(n
)/log(2)+1;for(int j
=1;j
<t
;j
++)for(int i
=1;i
<=n
-(1<<j
)+1;i
++) {if(a
[f
[i
][j
-1]]<a
[f
[i
+(1ll<<(j
-1))][j
-1]]) f
[i
][j
]=f
[i
][j
-1];else if(a
[f
[i
][j
-1]]>=a
[f
[i
+(1ll<<(j
-1))][j
-1]]) f
[i
][j
]=f
[i
+(1ll<<(j
-1))][j
-1];}}int query(int l
,int r
) {int t
=len
[r
-l
+1];if(a
[f
[l
][t
]]<a
[f
[r
-(1<<t
)+1][t
]]) return f
[l
][t
];else return f
[r
-(1<<t
)+1][t
];}void init() {top
=0;suf
[n
+1]=0; ssum
[n
+1]=0;}void get() {init(); rmq_init();memset(suf
,0,sizeof(suf
));memset(pre
,0,sizeof(pre
));memset(psum
,0,sizeof(psum
));memset(ssum
,0,sizeof(ssum
));for(int i
=1;i
<=n
;i
++) {while(top
&&a
[stk
[top
]]>a
[i
]) suf
[stk
[top
--]]=i
;pre
[i
]=stk
[top
]; stk
[++top
]=i
;}while(top
) pre
[stk
[top
]]=stk
[top
-1],suf
[stk
[top
--]]=n
+1;for(int i
=1;i
<=n
;i
++) psum
[i
]=(1ll*(i
-pre
[i
])*a
[i
]%mod
+psum
[pre
[i
]])%mod
;for(int i
=n
;i
>=1;i
--) ssum
[i
]=(1ll*(suf
[i
]-i
)*a
[i
]%mod
+ssum
[suf
[i
]])%mod
;pre
[0]=pre
[n
+1]=suf
[0]=suf
[n
+1]=0;for(int i
=1;i
<=n
;i
++) pre
[i
]=(pre
[i
-1]+psum
[i
])%mod
;for(int i
=n
;i
>=1;i
--) suf
[i
]=(suf
[i
+1]+ssum
[i
])%mod
;for(int i
=1;i
<=m
;i
++) {int l
=q
[i
].X
,r
=q
[i
].Y
;int pos
=query(l
,r
);LL ans
=1ll*(1ll*pos
-l
+1)*(r
-pos
+1)%mod
*a
[pos
]%mod
;ans
+=pre
[r
]-pre
[pos
]-psum
[pos
]*(r
-pos
)%mod
;ans
+=suf
[l
]-suf
[pos
]-ssum
[pos
]*(pos
-l
)%mod
;all
[i
]+=ans
%mod
; all
[i
]%=mod
;all
[i
]+=mod
; all
[i
]%=mod
;}}}x
;struct Node2 {void rmq_init(){memset(f
,0,sizeof(f
));for(int i
=1;i
<=n
;i
++) f
[i
][0]=i
;int t
=log(n
)/log(2)+1;for(int j
=1;j
<t
;j
++)for(int i
=1;i
<=n
-(1<<j
)+1;i
++) {if(a
[f
[i
][j
-1]]>a
[f
[i
+(1ll<<(j
-1))][j
-1]]) f
[i
][j
]=f
[i
][j
-1];else f
[i
][j
]=f
[i
+(1ll<<(j
-1))][j
-1];}}int query(int l
,int r
) {int t
=len
[r
-l
+1];if(a
[f
[l
][t
]]>a
[f
[r
-(1<<t
)+1][t
]]) return f
[l
][t
];else return f
[r
-(1<<t
)+1][t
];}void init() {top
=0;suf
[n
+1]=0; ssum
[n
+1]=0;}void get() {init(); rmq_init();memset(suf
,0,sizeof(suf
));memset(pre
,0,sizeof(pre
));memset(psum
,0,sizeof(psum
));memset(ssum
,0,sizeof(ssum
));for(int i
=1;i
<=n
;i
++) {while(top
&&a
[stk
[top
]]<a
[i
]) suf
[stk
[top
--]]=i
;pre
[i
]=stk
[top
]; stk
[++top
]=i
;}while(top
) pre
[stk
[top
]]=stk
[top
-1],suf
[stk
[top
--]]=n
+1;for(int i
=1;i
<=n
;i
++) psum
[i
]=(1ll*(i
-pre
[i
])*a
[i
]%mod
+psum
[pre
[i
]])%mod
;for(int i
=n
;i
>=1;i
--) ssum
[i
]=(1ll*(suf
[i
]-i
)*a
[i
]%mod
+ssum
[suf
[i
]])%mod
;pre
[0]=pre
[n
+1]=suf
[0]=suf
[n
+1]=0;for(int i
=1;i
<=n
;i
++) pre
[i
]=(pre
[i
-1]+psum
[i
])%mod
;for(int i
=n
;i
>=1;i
--) suf
[i
]=(suf
[i
+1]+ssum
[i
])%mod
;for(int i
=1;i
<=m
;i
++) {int l
=q
[i
].X
,r
=q
[i
].Y
;int pos
=query(l
,r
);LL ans
=1ll*(1ll*pos
-l
+1)*(r
-pos
+1)%mod
*a
[pos
]%mod
;ans
+=pre
[r
]-pre
[pos
]-psum
[pos
]*(r
-pos
)%mod
;ans
+=suf
[l
]-suf
[pos
]-ssum
[pos
]*(pos
-l
)%mod
;all
[i
]+=ans
%mod
; all
[i
]%=mod
;all
[i
]+=mod
; all
[i
]%=mod
;}}}y
;LL
qmi(LL a
,LL b
) {LL ans
=1; a
%=mod
;while(b
) {if(b
&1) ans
=ans
*a
%mod
;a
=a
*a
%mod
;b
>>=1;}return ans
%mod
;
}int main()
{
int _
; scanf("%d",&_
);while(_
--) {memset(all
,0,sizeof(all
));scanf("%d%d",&n
,&m
);for(int i
=1;i
<=n
;i
++) len
[i
]=(int)(log(i
)/log(2));for(int i
=1;i
<=n
;i
++) scanf("%d",&a
[i
]); for(int i
=1;i
<=m
;i
++) {int l
,r
; scanf("%d%d",&l
,&r
);q
[i
]={l
,r
};}for(int i
=1;i
<=m
;i
++) all
[i
]=0;x
.get(); y
.get();for(int i
=1;i
<=m
;i
++) printf("%lld\n",all
[i
]%mod
*qmi(2,mod
-2)%mod
*qmi(1ll*(1ll*q
[i
].Y
-q
[i
].X
+1)*(q
[i
].Y
-q
[i
].X
+1+1)/2,mod
-2)%mod
);}return 0;
}
總結
以上是生活随笔為你收集整理的HDU - 6989 Didn‘t I Say to Make My Abilities Average in the Next Life?! 莫队/单调栈 + 线段树/ST表在线的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。