A.直接二分长度ck一下区间是否有这些字母即可.

#include <bits/stdc++.h>
using namespace std;
const int N=2e5,M=20;
char s[N];
int pos[M][N];
int C(char c)
{
    if(c=='p')    return 1;
    if(c=='u')    return 2;
    if(c=='l')    return 3;
    if(c=='e')    return 4;
    if(c=='y')    return 5;
    if(c=='a')    return 6;
    if(c=='k')    return 7;
    if(c=='n')    return 8;
    if(c=='o')    return 9;
    if(c=='i')    return 10;
    return 0;
}
bool ck(int p,int len)
{
    int flag=1;
    for(int i=1;i<=10;i++)
    {
        if(pos[i][p+len-1]-pos[i][p-1]==0)    flag=0;
    }
    if(flag)    return true;
    else        return false;
}

int main()
{
    int T;
    cin>>T;
    while(T--)
    {
        scanf("%s",s+1);int len=strlen(s+1);
        for(int i=1;i<=len;i++)
        {
            int x=C(s[i]);
            for(int j=1;j<=10;j++)
            {
                pos[j][i]=pos[j][i-1]+(x==j);
            }
        }
        int ans=2e9;
        for(int i=1;i<=len;i++)
        {
            int l=10,r=len-i+1;
            while(l<=r)
            {
                int mid=(l+r)>>1;
                if(ck(i,mid))
                {
                    r=mid-1;
                    ans=min(ans,mid);
                }
                else l=mid+1;
            }
        }
        for(int i=1;i<=len;i++)
        {
            for(int j=1;j<=10;j++)
            {
                 pos[j][i]=0;
            }
        }
        ans==2e9?puts("-1"):printf("%d\n",ans);
    }
    return 0;
}

B.套用第一个题,不过这次要二分十次,每次贪心找到最小的即可.边界设置inf.

#include <bits/stdc++.h>
using namespace std;
const int N=2e5,M=20;
char s[N];
vector<int>v[M];
int C(char c)
{
    if(c=='p')    return 1;
    if(c=='u')    return 2;
    if(c=='l')    return 3;
    if(c=='e')    return 4;
    if(c=='y')    return 5;
    if(c=='a')    return 6;
    if(c=='k')    return 7;
    if(c=='n')    return 8;
    if(c=='o')    return 9;
    if(c=='i')    return 10;
    return 0;
}
bool ck(int p,int len)
{
    int pos1=p,pos2=p+len-1;
    for(int i=2;i<=10;i++)
    {
        pos1=*lower_bound(v[i].begin(),v[i].end(),pos1);

    }
    if(pos1<=pos2)    return true;
    else              return false;
}

int main()
{
    int T;
    cin>>T;
    while(T--)
    {
        scanf("%s",s+1);int len=strlen(s+1);
        for(int i=1;i<=10;i++)    v[i].clear();
        for(int i=1;i<=len;i++)
        {
            int x=C(s[i]);
            v[x].push_back(i);
        }
        for(int i=1;i<=10;i++)    v[i].push_back(2e9);
        int ans=2e9;
        for(int i=1;i<=len;i++)
        {
            if(s[i]=='p')
            {
                int l=10,r=len-i+1;
                while(l<=r)
                {
                    int mid=(l+r)>>1;
                    if(ck(i,mid))
                    {
                        r=mid-1;
                        ans=min(ans,mid);
                    }
                    else l=mid+1;
                }
            }
        }
        ans==2e9?puts("-1"):printf("%d\n",ans);
    }
    return 0;
}

C.循环节内可过,先预处理出来莫比乌斯函数,然后找循环节,最后输出答案即可.

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn =2e7+10;
int prime[maxn],mu[maxn],pcnt;
bool vis[maxn];
void init() 
{
    mu[1]=1;
    for(int i=2;i<maxn;i++)
    {
        if(!vis[i])
      {
            prime[++pcnt]=i;
            mu[i]=-1;
       }
        for(int j=1;i*prime[j]<maxn;j++)
      {
            vis[i*prime[j]]=1;
            if(i%prime[j]==0)
          {
                mu[i*prime[j]]=0;
                break;
            }
          else mu[i*prime[j]]=-mu[i];
        }
    }
}
int main()
{
    int T;
    cin >>T;
    init();
    while(T--) 
    {
        ll n,k;
        scanf("%lld%lld",&n,&k);
        vector<int>v;
        map<int,int> vis;
        int now=n;
        while(!vis[now]) 
        {
            v.push_back(now);
            vis[now]=1;
            now=now+mu[now];
        }
        int j;
        for (int i=0;i<v.size();i++)
            if(v[i]==now) {j=i;break;}
        vector<int>v1;
        for (int i=j;i<v.size();i++)
        v1.push_back(v[i]);
        if(k<v.size()) cout<<v[k]<<endl;
        else cout<<v1[(k-v.size())%v1.size()]<<'\n';
    }
    return 0;
}

D.拿set模拟删边,加边操作,然后最后输出ans即可.

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e6+10;
int u[maxn],v[maxn],a[maxn],op[maxn];
set<int>g[maxn];
int main()
{
    int n,cnt=0;
    cin>>n;
    for(int i=1;i<=n;i++) 
    {
        cin>>op[i];
        if(op[i]==3) continue;
        cin>>u[i]>>v[i];
        a[++cnt]=u[i];
        a[++cnt]=v[i];
    } 
    sort(a+1,a+1+cnt);
    cnt=unique(a+1,a+1+cnt)-a-1;
    for(int i=1;i<=n;i++) 
    {
        if(op[i]==3) continue;
        u[i]=lower_bound(a+1,a+1+cnt,u[i])-a;
        v[i]=lower_bound(a+1,a+1+cnt,v[i])-a;
    }
    int ans=0;
    for(int i=1;i<=n;i++) 
    {
        if(op[i]==1) 
        {
            if(g[u[i]].count(v[i])) continue;
            if(g[u[i]].size()&&g[v[i]].size()) ans--;
            else if(!g[u[i]].size()&&!g[v[i]].size()) ans++;
            g[u[i]].insert(v[i]);
            g[v[i]].insert(u[i]);
        }
        else if(op[i]==2) 
        {
            if(!g[u[i]].count(v[i])) continue;
            g[u[i]].erase(g[u[i]].find(v[i]));
            g[v[i]].erase(g[v[i]].find(u[i]));
            if(g[u[i]].size()&&g[v[i]].size()) ans++;
            else if(!g[u[i]].size()&&!g[v[i]].size()) ans--;
        }
        else cout<<ans<<endl;
    }
    return 0;
}