AtCoder Beginner Contest 381

AtCoder Beginner Contest 381 总结

https://atcoder.jp/contests/abc381

罚时吃爽了 qwq。

A

按题意模拟,判断一下即可。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <vector>
#include <queue>
#include <map>

using namespace std;
typedef long long ll;
const int N=105;
int n;
string s;

void solve()
{
    cin>>n>>s;
    bool st=1;
    if(n%2==0) st=0;
    for(int i=1;i<=(n+1)/2-1;i++) if(s[i-1]!='1') st=0;
    if(s[(n+1)/2-1]!='/') st=0;
    for(int i=(n+1)/2+1;i<=n;i++) if(s[i-1]!='2') st=0;
    if(st) cout<<"Yes\n";
    else cout<<"No\n";
}
int main()
{
    #ifndef ONLINE_JUDGE
    freopen("1.in","r",stdin);
    freopen("1.out","w",stdout);
    #endif 
    ios::sync_with_stdio(0);
    cin.tie(0);cout.tie(0);
    solve();
    return 0;
}

B

同样是按照题意判断。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <vector>
#include <queue>
#include <map>

using namespace std;
typedef long long ll;
const int N=105;
int n;
string s;
map<char,int> H;
void solve()
{
    cin>>s;
    n=s.size();
    bool st=1;
    if(n%2==1) st=0;
    for(int i=1;i<=n/2;i++) if(s[2*i-1]!=s[2*i-1-1]) st=0;
    for(int i=0;i<n;i++) H[s[i]]++;
    for(int i=0;i<n;i++) if(H[s[i]]!=2) st=0;
    if(st) cout<<"Yes\n";
    else cout<<"No\n";
}
int main()
{
    #ifndef ONLINE_JUDGE
    freopen("1.in","r",stdin);
    freopen("1.out","w",stdout);
    #endif 
    ios::sync_with_stdio(0);
    cin.tie(0);cout.tie(0);
    solve();
    return 0;
}

C

找到所有 / 的位置,向两边拓展,左边是 1,右边是 2

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <vector>
#include <queue>
#include <map>

using namespace std;
typedef long long ll;
const int N=2e5+5;
int n;
string s;
map<char,int> H;
void solve()
{
    cin>>n>>s;
    s="0"+s;
    int ans=0;
    for(int i=1;i<=n;i++)
    {
        if(s[i]=='/')
        {
            int k=0;
            while(i-k-1>=1&&i+k+1<=n&&s[i-k-1]=='1'&&s[i+k+1]=='2') k++;
            ans=max(ans,1+2*k);
        }
    }
    cout<<ans<<"\n";
}
int main()
{
    #ifndef ONLINE_JUDGE
    freopen("1.in","r",stdin);
    freopen("1.out","w",stdout);
    #endif 
    ios::sync_with_stdio(0);
    cin.tie(0);cout.tie(0);
    solve();
    return 0;
}

D

将数组 a 变成元素加个数的形式,元素数组为 b,个数为 c,如 1,1,2,2,3,3,3b 就是 1,2,3c 就是 2,2,3。用双指针来做。用 v 统计是否出现,j 表示左指针,i 表示右指针。统计答案就是 ij+1

  • ci=1 时,说明 i 不能贡献,直接将 j 移动到 i+1
  • ci>2 时,i 只能作为开头或结尾,若 bi 没出现过,统计一次答案。然后将 j 移动到 i,标记 bi 出现。
  • ci=2 时,若 bi 出现过,则一直移动 j 直到 vbi=0。然后标记 bi 出现。

移动 j 时要将 vbj 变为 0

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <vector>
#include <queue>
#include <map>

using namespace std;
typedef long long ll;
const int N=2e5+5;
int n;
int a[N],b[N],c[N];
int v[N];
void solve()
{
    cin>>n;
    int tot=0;
    for(int i=1;i<=n;i++) 
    {
        cin>>a[i];
        if(a[i]!=a[i-1]) b[++tot]=a[i],c[tot]=1;
        else c[tot]++;
    }
    int j=1,ans=0;
    for(int i=1;i<=tot;i++)
    {
        if(c[i]<2) while(j<=i) v[b[j++]]=0;
        else if(c[i]>2) 
        {
			if(!v[b[i]]) ans=max(ans,(i-j+1)*2);
            while(j<i) v[b[j++]]=0;
            v[b[i]]=1;
        }
        else 
        {
            while(j<=i&&v[b[i]]) v[b[j++]]=0;
            v[b[i]]=1;
        }
        if(j<=i) ans=max(ans,(i-j+1)*2);
    }
    cout<<ans<<'\n';
}
int main()
{
    #ifndef ONLINE_JUDGE
    freopen("1.in","r",stdin);
    freopen("2.out","w",stdout);
    #endif 
    ios::sync_with_stdio(0);
    cin.tie(0);cout.tie(0);
    solve();
    return 0;
}

E

首先处理 12/ 的前缀数量,并记录所有 / 的位置,用 p 记录。对于 lr,找到位于 [l,r] 的所有 / 的位置。lpLpRr。对于所有 i[L,R],设 id=pi,计算 [l,pi1]1 的数量 c1[pi+1,r]2 的数量 c2,通过前缀数组记录。显然贡献就是 min(c1,c2)×2+1。但是直接枚举 [L,R] 的话可能会超时,然而实际上这样就能过了 qwq。

记录:https://atcoder.jp/contests/abc381/submissions/60088312

update:更新了两组 hack 数据,把暴力的卡掉了。

考虑优化,i[L,R]i 逐渐增大时,c1 单调不减,c2 单调不增。而答案是取决于 c1c2 的最小值。可以用二分解决。

  • c1=c2 时,说明答案最大,直接结束。
  • c1<c2 时,说明 i 增加时答案可能更大,L=mid+1
  • c1>c2 时,说明 i 减小时才回使答案可能更大,R=mid1

对于每个 mid 计算答案。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <vector>
#include <queue>
#include <map>

using namespace std;
typedef long long ll;
const int N=1e5+5;
int n,q;
string s;
int a[N],b[N],c[N];
int p[N],tot;
void solve()
{
    cin>>n>>q;
    cin>>s;
    s="0"+s;
    for(int i=1;i<=n;i++) 
    {
        if(s[i]=='1') a[i]=1;
        else if(s[i]=='2') b[i]=1;
        else 
        {
            c[i]=1;
            p[++tot]=i;
        }
        a[i]+=a[i-1];
        b[i]+=b[i-1];
        c[i]+=c[i-1];
    }
    while(q--)
    {
        int l,r;
        cin>>l>>r;
        int L=lower_bound(p+1,p+tot+1,l)-p;
        int R=upper_bound(p+1,p+tot+1,r)-p-1;
        int ans=0;
        int mid,c1,c2,id;
        while(L<=R)
        {
            mid=L+R>>1;
            id=p[mid];
            c1=a[id-1]-a[l-1];
            c2=b[r]-b[id];
            ans=max(ans,2*min(c1,c2)+1);
            if(c1<c2) L=mid+1;
            else if(c1>c2) R=mid-1;
            else break;
        }
        cout<<ans<<'\n';
    }
}
int main()
{
    #ifndef ONLINE_JUDGE
    freopen("1.in","r",stdin);
    freopen("1.out","w",stdout);
    #endif 
    ios::sync_with_stdio(0);
    cin.tie(0);cout.tie(0);
    solve();
    return 0;
}

F

首先 a 的值域很小只有 20,可以支持 220,考虑用状压 dp。

状态 s,当 s 二进制下后面第 i1 时,表示 i 计算在答案中。s 的贡献为 2×|s|

f(s) 表示状态为 s 时,右端点的最小值。当 f(s)n 时说明 s 合法,可以贡献答案。

f(s) 只能由 t=s2if(t) 转移过来,显然 f(s)f(t) 后面的第二个 i 的位置。若不存在第二个 i ,令 f(s)=n+1 表示不合法。设 ne(i,j) 表示数组 a[i+1,n] 中第一个 j+1 的位置,则有 f(s)=min0i<|s|(ne(ne(f(t),i),i))

预处理所有 ne(i,j) 还是比较好办的,直接看代码吧。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <vector>
#include <queue>
#include <map>

using namespace std;
typedef long long ll;
const int N=2e5+5,M=20,S=1<<20;
int n;
int a[N],ne[N][M];
int f[S];
void solve()
{
    cin>>n;
    for(int i=1;i<=n;i++) cin>>a[i];
    for(int i=0;i<M;i++) ne[n][i]=ne[n+1][i]=n+1;
    for(int i=n-1;i>=0;i--)
    {
        for(int j=0;j<M;j++) ne[i][j]=ne[i+1][j];
        ne[i][a[i+1]-1]=i+1;
    }
    for(int i=0;i<S;i++) f[i]=n+1;
    f[0]=0;
    int ans=0;
    for(int i=0;i<S;i++)
    {
        int cnt=0;
        for(int j=0;j<M;j++)
            if(i&(1<<j)) 
            {
                cnt+=2;
                f[i]=min(f[i],ne[ne[f[i^(1<<j)]][j]][j]);
            }
        if(f[i]<=n) ans=max(ans,cnt);
    }
    cout<<ans<<'\n';
}
int main()
{
    #ifndef ONLINE_JUDGE
    freopen("1.in","r",stdin);
    freopen("1.out","w",stdout);
    #endif 
    ios::sync_with_stdio(0);
    cin.tie(0);cout.tie(0);
    solve();
    return 0;
}

posted @   zhouruoheng  阅读(121)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效
点击右上角即可分享
微信分享提示