Codeforces Round 979 (Div. 2)

C. A TRUE Battle

如果开头和结尾有 $1$,那么一定 Alice 胜

如果中间有相邻的两个 $1$,那么 Alice 可以先选这俩中间 Or 再任选一边 Or 最后一定胜

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <bits/stdc++.h>
using namespace std;

void solve(){
    int n;
    string s;
    cin>>s;
    if(s[0]=='1'||s[n-1]=='1')cout<<"YES\n";
    for(int i=0;i<n;i++){
        if((s[i]-'0')&&(s[i+1]-'0')==1){
            cout<<"YES\n";
            return;
        }
    }
    cout<<"NO\n";
}

int main(){
    int t;
    cin>>t;
    while(t--)solve();
}

D. QED’s Favorite Permutation

观察题目发现,除非出现 $LR$ 这样的片段,不然就会形成一个片段,这个片段中的每个元素都可以互换位置。

那么就可以判断每个片段中是否有不属于这个片段的元素存在,如果有即为 NO,反之为 YES

开一 $cnt$ 数组来记录位置错乱的值,如果前缀和 $cnt=0$ 那么当前片段即为可行片段

如果出现了 $LR$ 同时 $cnt!=0$ 那么答案就为 NO

只需要实时更新不合法的位置即可

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
#include <bits/stdc++.h>
using namespace std;
#define ls now<<1
#define rs now<<1|1
#define endl "\n"
#define lowbit(x) ((x)&(-x))
typedef long long ll;
const int N=2e5+7, mod=1e9+7;

int n,q;
int p[N],cnt[N];
string s;
set<int>st;

void solve(){
    cin>>n>>q;
    for(int i=1;i<=n;i++)cin>>p[i];
    for(int i=1;i<=n;i++){
        cnt[min(i,p[i])]++;
        cnt[max(i,p[i])]--;
    }
    for(int i=2;i<=n;i++)cnt[i]+=cnt[i-1];
    cin>>s;
    s=" "+s;
    for(int i=1;i<n;i++){
        if(s[i]=='L'&&s[i+1]=='R'&&cnt[i])st.insert(i);
    }
    while(q--){
        int x;
        cin>>x;
        s[x]=(s[x]=='L'?'R':'L');
        if(s[x-1]=='L'&&s[x]=='R'&&cnt[x-1])st.insert(x-1);
        else st.erase(x-1);
        if(s[x]=='L'&&s[x+1]=='R'&&cnt[x])st.insert(x);
        else st.erase(x);
        if(!st.empty())cout<<"NO\n";
        else cout<<"YES\n";
    }
    st.clear();
    memset(cnt,0,sizeof(cnt));
}

int main(){
    ios::sync_with_stdio(0);
    cin.tie(0);cout.tie(0);
    int t=1;
    cin>>t;
    while(t--)solve();
    return 0;
}

有点类似的两道题

CF Round 977

C1. Adjust The Presentation (Easy Version)

初始序列的某个成员,他在播放序列中出现的顺序一定比他后面的人前,不可能在播放序列中出现倒序的情况

相当与只考虑实际初始序列中的相邻位置,如果上一个人没有播放过,或者他播放的顺序比后面那个晚,那一定不可能达成

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
#include <bits/stdc++.h>
using namespace std;
#define ls now<<1
#define rs now<<1|1
#define endl "\n"
#define lowbit(x) ((x)&(-x))
typedef long long ll;
const int N=2e5+7, mod=1e9+7;

int n,m,q;
int a[N],b[N],c[N];

void solve(){
    cin>>n>>m>>q;
    for(int i=1;i<=n;i++)cin>>a[i];
    for(int i=1;i<=m;i++)cin>>b[i];
    memset(c,0x3f3f3f,sizeof(c));
    for(int i=1;i<=m;i++){
        if(c[b[i]]>N)c[b[i]]=i;
    }
    for(int i=2;i<=n;i++){
        int now=a[i],lst=a[i-1];
        if(c[now]<N&&c[lst]>N||c[now]<c[lst]){
            cout<<"TIDAK\n";
            return;
        }
    }
    cout<<"YA\n";
}

int main(){
    ios::sync_with_stdio(0);
    cin.tie(0);cout.tie(0);
    int t=1;
    cin>>t;
    while(t--)solve();
    return 0;
}

C2. Adjust The Presentation (Hard Version)

与 C1 相比,加了 Q 次可持久化更改和询问

实际思路仍和上题相似

我们可以维护不合法的所有位置,即初始序列中那些相邻的前者未播放,或后者先于前者在播放序列出现的组合

将所有的不合法组合储存起来,每次更新检查剩下的组合是否为 0,如果为 0 即总序列为合法

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
#include <bits/stdc++.h>
using namespace std;
#define ls now<<1
#define rs now<<1|1
#define endl "\n"
#define lowbit(x) ((x)&(-x))
typedef long long ll;
const int N=1e6+7, mod=1e9+7;
const ll inf=1e16;

int n,m,q;
int a[N],b[N],c[N],d[N];
set<int>s[N];

int check(int x){
    int cnt=0,l=a[x-1],r=a[x+1],now=a[x];
    if(x<n&&d[now]>d[r])cnt++;
    if(x>1&&d[l]>d[now])cnt++;
    return cnt;
}

void solve(){
    memset(c, 0, sizeof(c));
    cin >> n >> m >> q;
    for(int i = 1; i <= n; i++){
        cin >> a[i];
        s[i].clear();
        c[a[i]] = i;
        d[i] = inf;
    }
    for(int i = 1; i <= m; i++){
        cin >> b[i];
        s[b[i]].insert(i);
    }
    for(int i = m; i > 0; i--) d[b[i]] = i;
    int cnt = 0;
    for(int i = 1; i < n; i++){
        if(d[a[i]] > d[a[i + 1]]) cnt++;
    }
    if(!cnt) cout << "YA\n";
    else cout << "TIDAK\n";
    while(q--){
        int x, y;
        cin >> x >> y;
        s[b[x]].erase(x);
        s[y].insert(x);
        for(int i:{b[x],y}){
            cnt-=check(c[i]);
            if(s[i].empty())d[i]=inf;
            else d[i]=*s[i].begin();
            cnt+=check(c[i]);
        }
        b[x]=y;
        if(!cnt)cout<<"YA\n";
        else cout<<"TIDAK\n";
    }
}

int main(){
    ios::sync_with_stdio(0);
    cin.tie(0);cout.tie(0);
    int t=1;
    cin>>t;
    while(t--)solve();
    return 0;
}
Licensed under CC BY-NC-SA 4.0
最后更新于 Sep 11, 2025 16:27 +0800
发表了95篇文章 · 总计15万2千字
永远相信美好的事情即将发生。
使用 Hugo 构建
主题 StackJimmy 设计