首页 > 其他分享 >题解:P11207 「Cfz Round 9」Rose

题解:P11207 「Cfz Round 9」Rose

时间:2024-10-22 20:48:33浏览次数:6  
标签:frac int 题解 else lst Cfz 答案 Rose define

可以考虑把字符串 \(s\),\(t\) 按 \(s_1 t_1 s_2 t_2 \dots s_n t_n\) 拼接,记为 \(a\)。为了方便表述,这里分别把 PVW 表示为 012

Subtask 0

我会暴力!可以直接在 \(a\) 上进行 dfs,复杂度为 \(O(3^{2n})\)。

Subtask 1

我会找性质!注意到答案只有可能是 \(0,1,2\),因为在最坏情况下,只要 \(2\) 次操作把 \(a_1,a_2,a_3\) 改成互不相同的数就行了。

首先我们可以 \(O(n)\) 判断答案是否为 \(0\)。接下来判断答案是否为 \(1\),我们可以枚举修改哪个位置,再扫一遍 \(a\) 就可以了。剩下的情况的答案必然为 \(2\)。总复杂度为 \(O(n^2)\)。

Subtask 4

考虑在判断答案是否为 \(1\) 的过程上优化,可以发现答案为 \(1\) 时,设获胜的位置为 \(i\),\(s_{0/1/2}\) 表示 \(a_1 \sim a_i\) 中 \(0,1,2\) 出现的个数,则 \(3 \mid i\) 且 \(\{s0,s1,s2\}=\{\frac{i}{3}-1,\frac{i}{3},\frac{i}{3}+1\}\)。于是我们就记录每个 \(a_i\) 最后出现的位置。

但是,如果把某个位置修改后,自己比对手先赢,就会出现问题。于是,我们设 \(lst_{i,j}\) 表示最前的把 \(i\) 改为 \(j\) 且不会出现这种情况的位置。每次出现 \(3 \mid i\) 且 \(\{s0,s1,s2\}=\{\frac{i}{3}-1,\frac{i}{3},\frac{i}{3}+1\}\) 时,如果 \(i\) 为偶数,就把操作一次会赢的 \(lst_{i,j}\) 清空,否则若 \(i\) 为奇数,如果存在符合的 \(lst_{i,j}\),答案就为 \(1\)。

最后,如果在自己在 \(pos\) 位置不做操作就已经赢了,还需要满足 \(lst_{i,j} \leq pos\)。

这些都可以 \(O(n)\) 维护。

代码:(这里的 \(lst_{i,j}\) 进行了状态压缩)

#include<bits/stdc++.h>
using namespace std;
#define int long long
#define flush() fwrite(obuf,1,O-obuf,stdout)
#define putchar(x) ((O==obuf+(1<<21))&&(flush(),O=obuf)),*O++=x
char buf[1<<23],*p1=buf,*p2=buf,obuf[1<<23],*O=obuf;
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
inline int read() {
    register int x=0,f=1;register char ch=getchar();
    while(!isdigit(ch)){if(ch=='-') f=-1;ch=getchar();}
    while(isdigit(ch)) x=x*10+(ch^48),ch=getchar();
    return x*f;
}
inline void write(register int x){
    if(x<0) putchar('-'),x=-x;
    if(x>9) write(x/10);
    putchar((x%10)^48);
}
struct Flush{
    ~Flush(){flush();}
}_;
#define N 100010
int t,n,a[N*2],ans;
signed main(){
    int T;
    cin>>t;
    T=t;
    while(t--){
        ans=556676;
        cin>>n;
        for(int i=1;i<=2*n;i++){
            a[i]=0;
        }
        for(int i=1;i<=n;i++){
            char c;
            cin>>c;
            if(c=='P'){
                a[2*i-1]=0;
            }
            else{
                if(c=='V'){
                    a[2*i-1]=1;
                }
                else{
                    a[2*i-1]=2;
                }
            }
        }
        for(int i=1;i<=n;i++){
            char c;
            cin>>c;
            if(c=='P'){
                a[2*i]=0;
            }
            else{
                if(c=='V'){
                    a[2*i]=1;
                }
                else{
                    a[2*i]=2;
                }
            }
        }
            int s[3]={};
            for(int i=1;i<=2*n;i++){
                s[a[i]]++;
                if(s[0]==s[1]&&s[1]==s[2]){
                    if(i%2==1){
                        ans=0;
                    }
                    break;
                }
            }
            if(ans==0){
                cout<<0<<endl;
                continue;
            }
            s[0]=s[1]=s[2]=0;
            int pos=2*n;
            int lst[9]={};
            for(int i=1;i<=2*n;i++){
                if(i<=pos){
                    lst[a[i]*3+0]=lst[a[i]*3+1]=lst[a[i]*3+2]=i;
                }
                s[a[i]]++;
                if(i%2==0){
                    if(s[0]==s[1]&&s[0]==s[2]){
                        pos=min(pos,i);
                        continue;
                    }
                    if(s[0]==s[1]-1&&s[1]==s[2]-1){
                        lst[6]=0;
                    }
                    if(s[0]==s[2]-1&&s[2]==s[1]-1){
                        lst[3]=0;
                    }
                    if(s[1]==s[0]-1&&s[0]==s[2]-1){
                        lst[7]=0;
                    }
                    if(s[1]==s[2]-1&&s[2]==s[0]-1){
                        lst[1]=0;
                    }
                    if(s[2]==s[0]-1&&s[0]==s[1]-1){
                        lst[5]=0;
                    }
                    if(s[2]==s[1]-1&&s[1]==s[0]-1){
                        lst[2]=0;
                    }
                }
                else{
                    if(s[0]==s[1]-1&&s[1]==s[2]-1){
                        if(lst[6]&&lst[6]<=pos){
                            ans=1;
                            break;
                        }
                    }
                    if(s[0]==s[2]-1&&s[2]==s[1]-1){
                        if(lst[3]&&lst[3]<=pos){
                            ans=1;
                            break;
                        }
                    }
                    if(s[1]==s[0]-1&&s[0]==s[2]-1){
                        if(lst[7]&&lst[7]<=pos){
                            ans=1;
                            break;
                        }
                    }
                    if(s[1]==s[2]-1&&s[2]==s[0]-1){
                        if(lst[1]&&lst[1]<=pos){
                            ans=1;
                            break;
                        }
                    }
                    if(s[2]==s[0]-1&&s[0]==s[1]-1){
                        if(lst[5]&&lst[5]<=pos){
                            ans=1;
                            break;
                        }
                    }
                    if(s[2]==s[1]-1&&s[1]==s[0]-1){
                        if(lst[2]&&lst[2]<=pos){
                            ans=1;
                            break;
                        }
                    }
                }
            }
            if(ans==1){
                cout<<1<<endl;
            }
            else{
                cout<<2<<endl;
            }
    }
    return 0;
}

标签:frac,int,题解,else,lst,Cfz,答案,Rose,define
From: https://www.cnblogs.com/awmmmmmm/p/18493714

相关文章

  • 题解:P11204 「Cfz Round 9」Lone
    首先可以观察出把木棍平均分是最优的。然后平均分后最多只有两种长度的木棒,长度分别为\(\lfloor\frac{m}{n}\rfloor\)和\(\lfloor\frac{m}{n}\rfloor+1\)。最后check一下就行了。代码:#include<bits/stdc++.h>usingnamespacestd;#defineintlonglong#define......
  • P2934 [USACO09JAN] Safe Travel G 题解
    一个用平衡树,不用脑子的写法。(目前没有用平衡树的诶。)题意不经过最短路的最后一条边的最短路,保证最短路唯一。思路看到最短路唯一容易想到建出的最短路DAG其实是最短路树(以\(1\)为根)。那题意转化为求每个节点不经过与父亲的连边,所能到根节点的最短路。容易发现每个点的......
  • 【NOIP2021】方差 题解
    前言题目链接:洛谷;LOJ;UOJ。题意简述给你单调不降序列\(\{a_n\}\),你可以让\(a_i\getsa_{i-1}+a_{i+1}-a_i\),求操作后方差的最小值。\(n\leq10^4\),\(1\leqa_i\leq600\)。题目分析仔细观察操作,发现实际上是将\(a_i\)按照\(a_{i-1}\)和\(a_{i+1}\)的......
  • 题解:P10977 Cut the Sequence
    题目传送门分析看到这种题就可以想到动态规划,先设状态:$f_i$表示考虑前$i$个数,所需要的最小代价。发现$f_i$可以从所有$i$以前的状态加后一段区间转移过来,于是可以列出状态转移方程:$$f_i=\min_{j=i-1}^{s_i-s_j\leqm}(f_j+\max_{k=j+1}^i)$$其中$j$......
  • [题解]P2671 [NOIP2015 普及组] 求和
    P2671[NOIP2015普及组]求和可以发现我们对相同颜色且编号奇偶性相同的元素归为一组,组内的元素两两都满足题目条件,且这样可以不重不漏覆盖所有答案。设分完组之后,某一组内的元素编号分别是\(a_1,a_2,\dots,a_q\),数字分别是\(b_1,b_2,\dots,b_q\),则根据题意,该组的答案是:\[\lar......
  • 20241021 校测T1 致敬传奇捆绑测试题目(Perm) 题解
    题解:致敬传奇捆绑测试题目Perm来自不知道什么时候的回忆。给定正整数\(n\),一个\(1\simn\)的排列\(p\)是一个好排列,当且仅当使得对于任意\(1\lek<n\),都有\(\sum_{i=1}^kp_i>p_{k+1}\)。现在请你求出字典序第小的好排列\(p\)。\(1\len\le10^6\),\(1\lek\le......
  • [ARC133E] Cyclic Medians 题解
    一点不会套路。思路对于中位数相关,发现我们不好直接表示与中位数有关的内容。不妨枚举\(x\),把大于\(x\)的标为\(1\),小于等于\(x\)的标为\(0\),这样把所有最终为一的方案数加起来就是原来的答案。大概是这样一个东西:\[k=\sum_{i=0}^k[i<k]\]这个怎么求呢。发现若一组......
  • Public NOIP Round #7 T3 黑白棋子 题解
    Description有一棵\(n\)个点的树,顶点的编号为\(1\)到\(n\)。对于树中的每个顶点,可能存在一个白色的棋子、一个黑色的棋子,或者没有棋子。树上正好有\(w\)个白色棋子和\(b\)个黑色棋子。另外,对于每一对具有相同颜色棋子的顶点,存在一条路径,路径上的每个顶点都包含相同颜色......
  • AT_agc064_c [AGC064C] Erase and Divide Game 题解
    先考虑所有\(l_i=r_i\)时怎么做,可以建出反向Trie树,问题转化为从根开始每次向左子树或右子树走,第一个拿到空子树的人输,直接在Trie上dp即可。考虑从叶子层开始对每一层的点合并两个子树的dp值,发现每一层值相同的连续段是较少的。于是可以维护这些连续段,每次合并要将每个......
  • 洛谷P2596 [ZJOI2006] 书架 题解 splay tree 模板题
    题目链接:https://www.luogu.com.cn/problem/P2596主要涉及的操作就是:找到某一个编号的点(这个操作可以不用splaytree维护)删除某个点将某一个点插入到最前面,最后面,或者某一个位置查询前序遍历为\(k\)的节点编号因为每次删除都会又把这个点加回去,所以可以复用\(n\)个......