传送门:https://codeforces.com/contest/1236/problem/E
题意:
给定一个$1*n$的格子,每次$Alice$会移动一次棋子,$Marisa$会猜测棋子在哪,猜测的顺序以一个序列的形式给定
问有多少组$(x,y)$,$x$表示起点,$y$表示终点,$Alice$能赢
$n<=10^{5}$
sol:
一个比较显然的性质
一个点可以到达的最左/最右的点是确定的,可以到达的点是一个区间。
每个数列值$a_i$只会影响一个起点
我们只需要求出对于每个起点,它的左极限/右极限在哪就行了qwq
我们可以贪心地走,一次只考虑一个半边
对于一个半边,如果没有障碍我们就一直走,有障碍的话就停一步再走
这个东西对于一个点的一个半边,通过预处理障碍影响,是可以$O(1)$地统计的
然后总效率就是$O(N)$
#include <bits/stdc++.h> using namespace std; int N,M; int a[100005],b[100005],l[100005],r[100005]; void SolveR(){ for (int i=1;i<=M;i++) b[i]=a[i]; for (int i=1;i<=M;i++) a[i]-=i; map<int,int> qwq; for (int i=M;i>=1;i--) qwq[a[i]]=qwq[a[i]-1]+1; for (int i=1;i<=N;i++) r[i]=min(i+M+1-qwq[i],N);//get the most right pos for (int i=1;i<=M;i++) a[i]=b[i]; } void SolveL(){ for (int i=1;i<=M;i++) b[i]=a[i]; for (int i=1;i<=M;i++) a[i]+=i; map<int,int> qwq; for (int i=M;i>=1;i--) qwq[a[i]]=qwq[a[i]+1]+1; for (int i=1;i<=N;i++) l[i]=max(i-M-1+qwq[i],1);//get the most left pos for (int i=1;i<=M;i++) a[i]=b[i]; } int main(){ scanf("%d%d",&N,&M); for (int i=1;i<=M;i++) scanf("%d",&a[i]); if (N==1) { puts("0"); return 0; } SolveL(); SolveR(); long long ans=0; for (int i=1;i<=N;i++) ans+=(r[i]-l[i])+1; cout<<ans; return 0; }