【BZOJ-3956】Count ST表 + 单调栈
3956: Count
Time Limit: 10 Sec Memory Limit: 512 MBSubmit: 173 Solved: 99
[Submit][Status][Discuss]
Description
Input
Output
Sample Input
3 2 0
2 1 2
1 1
1 3
2 1 2
1 1
1 3
Sample Output
0
3
3
HINT
M,N<=3*10^5,Ai<=10^9
Source
CH Round#64 MFOI杯水题欢乐赛day1 By Gromah
Solution
思路有了之后,比较好写的一道题
首先我们计算以每个点为区间左端的答案,以及区间右端的答案,利用单调栈可以$O(N)$的处理出来
同样可以预处理出它们的前缀和
然后我们考虑一次询问,假如我们得到$[l,r]$中的最大值位置mp
那么我们的答案,相当于是询问区间$[l,mp]$中所有点作为左端的答案与$[mp+1,r]$中所有点作为右端点的答案
那么显然前缀和计算就好,至于查询最大位置?线段树/ST表都可以处理
这里采用ST表,总复杂度是$O(NlogN+M)$
Code
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> using namespace std; inline int read() { int x=0,f=1; char ch=getchar(); while (ch<'0' || ch>'9') {if (ch=='-') f=-1; ch=getchar();} while (ch>='0' && ch<='9') {x=x*10+ch-'0'; ch=getchar();} return x*f; } #define MAXN 300010 int N,M,T,h[MAXN]; long long last; inline int GetL (int x,int y) {if (T) return min((x+last-1)%N,(y+last-1)%N)+1; else return min(x,y);} inline int GetR (int x,int y) {if (T) return max((x+last-1)%N,(y+last-1)%N)+1; else return max(x,y);} int log2[MAXN],dp[MAXN][21]; inline int MaxPos(int x,int y) {return h[x]>h[y]? x:y;} void ST() { log2[0]=-1; for (int i=1; i<=N; i++) if (i&(i-1)) log2[i]=log2[i-1]; else log2[i]=log2[i-1]+1; for (int i=1; i<=N; i++) dp[i][0]=i; for (int j=1; (1<<j)<=N; j++) for (int i=1; i+(1<<j)-1<=N; i++) dp[i][j]=MaxPos(dp[i][j-1],dp[i+(1<<(j-1))][j-1]); } inline int RMQ(int l,int r) { int tmp=log2[r-l+1]; return MaxPos(dp[l][tmp],dp[r-(1<<tmp)+1][tmp]); } long long AnsL[MAXN],AnsR[MAXN]; int stack[MAXN],top; void PreWork() { top=0; stack[++top]=h[1]; for (int i=2; i<=N; i++) { while (top && h[i]>stack[top]) AnsL[i]++,top--; if (top) AnsL[i]++; while (top && h[i]>=stack[top]) top--; stack[++top]=h[i]; } top=0; stack[++top]=h[N]; for (int i=N-1; i>=1; i--) { while (top && h[i]>stack[top]) AnsR[i]++,top--; if (top) AnsR[i]++; while (top && h[i]>=stack[top]) top--; stack[++top]=h[i]; } for (int i=1; i<=N; i++) AnsL[i]+=AnsL[i-1],AnsR[i]+=AnsR[i-1]; ST(); } inline void Solve(int L,int R) { int maxp=RMQ(L,R); printf("%lld\n",last=AnsR[maxp-1]-AnsR[L-1]+AnsL[R]-AnsL[maxp]); } int main() { N=read(),M=read(),T=read(); for (int i=1; i<=N; i++) h[i]=read(); PreWork(); while (M--) { int x=read(),y=read(); int L=GetL(x,y),R=GetR(x,y); Solve(L,R); } return 0; }
——It's a lonely path. Don't make it any lonelier than it has to be.