atcoder beginner contest 416

A

void solve(){
    int n;cin>>n;
    int l,r;cin>>l>>r;

    string s;cin>>s;
    s=" "+s;
    for(int i=l;i<=r;i++){
        if(s[i]=='x'){
            cout<<"No"<<endl;
            return;
        }
    }
    cout<<"Yes"<<endl;
}

B

题意:给定一个由#,.,o组成的字符串,修改字符串的.,使得o尽量多,且满足每个o之间隔着一个#

void solve(){
    string s;cin>>s;
    int n=s.size();
    s=" "+s;
    vector<char>t(n+1);
    vector<int>vis(n+1);
    rep(i,1,n){
        if(s[i]=='#'){
            t[i]='#';
            vis[i]=1;
        }
    }
    //1 0
    //2 3
    int last=0;
    rep(i,1,n){
        if(s[i]=='#'){
            int ok=0;
            for(int j=last+1;j<=i-1;j++){
                if(s[j]=='o')ok=1;
            }

            if(ok)break;
            else{
                for(int j=last+1;j<=i-1;j++){
                    if(s[j]=='.'){
                        s[j]='o';break;
                    }
                }
            }
            last=i;

        }
    }
    int ok=0;
    for(int j=last+1;j<=n;j++){
        if(s[j]=='o')ok=1;
    }
    if(!ok){
        for(int j=last+1;j<=n;j++){
            if(s[j]=='.'){
                s[j]='o';
                break;
            }
        }
    }
    rep(i,1,n){
        cout<<s[i];
    }
}

C

题意:给定n个字符串,把其中的k个拼接在一起,求字典序第x小的字符串
思路:
n^k<1e5,dfs+排序即可

int n,k,x;
vector<string>v;
void dfs(string s,vector<string>&a,int cal){
    if(cal==k){
        v.pb(s);return;
    }
    for(int i=1;i<=n;i++){
        dfs(s+a[i],a,cal+1);
    }
}
void solve(){
    cin>>n>>k>>x;
    vector<string>a(n+1);
    rep(i,1,n)cin>>a[i];
    dfs("",a,0);
    sort(v.begin(),v.end());
    x--;
    cout<<v[x]<<endl;
}

D

题意:给定两个数组a和b和数字m,可以重排a,使得 sigma(1<=i<=n)(a_i+b_i)%m 最小
思路:
贪心
发现ai和bi的范围都是小于m的
因此我们有 0<ai+bi<2m
所以 ai+bi = c 或 ai+bi = m + c (c<m)
我们的目标是减小c之和
枚举b,发现要么取a中最小的,要么取 ai= m+c -bi ,即ai中大于等于m-bi的
两者比较取min
a的元素考虑使用multiset维护
显然,这样局部贪心能获得最优解

void solve(){
    int n,m;cin>>n>>m;
    vector<int>a(n+1);rep(i,1,n)cin>>a[i];
    vector<int>b(n+1);rep(i,1,n)cin>>b[i];
    vector<int>vis(n+1);
    multiset<int>at;
    rep(i,1,n)at.insert(a[i]);
    sort(a.begin()+1,a.end());
    int ans=0;
    rep(i,1,n){
        int res=(b[i]+*(at.begin()))%m;

        auto it=at.lower_bound(m-b[i]);
        if(it!=at.end()){
            int res2=(b[i]+*(it))%m;

            if(res2<res){
                at.erase(it);
                ans+=res2;
            }else{
                at.erase(at.begin());
                ans+=res;
            }
        }else{
            at.erase(at.begin());
            ans+=res;
        }
    }
    cout<<ans<<endl;
}

E

题意:给定n个点的图(n<=500),m条边长度为C_i,其中有k个点有机场可以相互以T的时间到达
3种查询

  • 1.x,y之间建一条长度为c的边
  • 2.在x点上建一个机场
  • 3.输出 sigma(1<=i<j<=n)f(i,j)(其中f(i,j)表示i->j的最短路,当然图是无向的)

查询次数q<=1000

思路:
n=500,显然floyd
只有1,3查询的话,十分容易维护,只需要在加边的时候n^2判断一下i->j的最短路是否变为i->x->y->j或i->y->x->j即可

对于查询2,我们直接建边发现不好维护

不妨设一个sky点(第n+1个点),其中有机场的点到sky耗费T,sky到有机场的点耗费0

这样和上述一样维护就可以,floyd此时跑n+1

int d[505][505];
int air[505];
void solve(){
    int n,m;cin>>n>>m;
    int sky=n+1;
    rep(i,1,n+1)rep(j,1,n+1){
        if(i==j)continue;
        d[i][j]=1e18;
    }
    //第n+1点为sky点
    //有机场的点可以以T的代价到达sky点
    //sky点可以以0的代价到达任意有机场的点
    rep(i,1,m){
        int u,v,c;cin>>u>>v>>c;
        d[u][v]=min(d[u][v],c);
        d[v][u]=min(d[v][u],c);
    }
        int k,T;cin>>k>>T;
        rep(i,1,k){
            int x;cin>>x;
            air[x]=1;
            d[x][sky]=T;
            d[sky][x]=0;
        }



    {//floyd
    rep(k,1,n+1){
        rep(i,1,n+1){
            rep(j,1,n+1){
                d[i][j]=min(d[i][j],d[i][k]+d[k][j]);
            }
        }
    }
    }

    int q;cin>>q;
    while(q--){
        int opt;cin>>opt;
        if(opt==1){
            int x,y,c;cin>>x>>y>>c;
            int tmp=d[x][y];
            d[x][y]=min(d[x][y],c);
            d[y][x]=min(d[y][x],c);
            if(tmp>c){
                rep(i,1,n+1){
                    rep(j,1,n+1){
                        d[i][j]=min({d[i][j],d[i][x]+c+d[y][j],d[i][y]+c+d[x][j]});
                    }
                }
            }
        }else if(opt==2){
            int x;cin>>x;
            if(air[x])continue;
            air[x]=1;
            d[x][sky]=T;
            d[sky][x]=0;
            rep(i,1,n+1){
                rep(j,1,n+1){
                    d[i][j]=min({d[i][j],d[i][x]+T+d[sky][j],d[i][sky]+0+d[x][j]});
                }
            }
        }else{
            int ans=0;
            rep(i,1,n){
                rep(j,i+1,n){
                    ans+=(d[i][j]>=1e18?0:d[i][j]);
                }
            }
            cout<<ans*2<<endl;
        }
    }
}
posted @ 2025-07-26 22:39  Marinaco  阅读(37)  评论(0)    收藏  举报
//雪花飘落效果