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

分析

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

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

显然当 cnt=n1 时,满足题目条件。

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

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

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

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


但是如果 xy 相邻,可能会有错误的贡献,这时需要特判。

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';
}
}

本文作者:Jimmy-LEEE

本文链接:https://www.cnblogs.com/redacted-area/p/18429454

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   Jimmy-LEEE  阅读(4)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起