W
e
l
c
o
m
e
: )

题解:P9757 [COCI2022-2023#3] Dirigent

分析

\(a[i]\) 为第 \(i\) 位的人的编号,\(\operatorname{pre}(i)\) 为第 \(i\) 位前一个的人。

\(cnt\) 为满足 \(a[\operatorname{pre}(i)]+1=a[i]\)\(i\) 的个数。

显然当 \(cnt=n-1\) 时,满足题目条件。

我们可以在一开始预先 \(O(n)\) 处理出 \(cnt\)

考虑一次交换操作带来的贡献。

对于任意一个人,可以 \(O(1)\) 算出他和他前后的人产生的贡献。

所以 \(O(1)\) 算出要交换的人 \(x\)\(y\) 的贡献,将 \(cnt\) 减去原贡献后再加上新的贡献。


但是如果 \(x\)\(y\) 相邻,可能会有错误的贡献,这时需要特判。

Code

#include<bits/stdc++.h>
using namespace std;
#define maxn 300005

int a[maxn], pos[maxn];
#define pre(i) (((i)==1)?(n):((i)-1))
#define nxt(i) (((i)==n)?(1):((i)+1))
#define chkpre(x) (a[x]==a[pre(x)]+1)
#define chknxt(x) (a[x]+1==a[nxt(x)])

int main()
{
    int n, q, x, y;
    cin>>n>>q;
    int cnt=0;
    for(int i=1;i<=n;i++) cin>>a[i], pos[a[i]]=i;
    for(int i=1;i<=n;i++)
        if(a[i]==a[pre(i)]+1) cnt++;
    while(q--)
    {
        cin>>x>>y;
        if(pre(x)==y) swap(x, y);
        int nx=x, ny=y;
        x=pos[x], y=pos[y];
        cnt-=chkpre(x)+chknxt(x)+chkpre(y)+chknxt(y);
        if(nxt(x)==y&&a[x]+1==a[y]) cnt++; 
        swap(a[x], a[y]);
        swap(pos[nx], pos[ny]);
        cnt+=chkpre(x)+chknxt(x)+chkpre(y)+chknxt(y);
        swap(x, y);
        if(nxt(x)==y&&a[x]+1==a[y]) cnt--; 
        cout<<(cnt==n-1?"DA":"NE")<<'\n';
    }
}
posted @ 2024-09-24 16:30  Jimmy-LEEE  阅读(25)  评论(0)    收藏  举报