Codeforces Round #593 (Div. 2) E.Alice and the Unfair Game

传送门: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;
}

猜你喜欢

转载自www.cnblogs.com/si--nian/p/11716462.html