zoukankan      html  css  js  c++  java
  • Codeforce1196_D_F

    D RGB Substring

    题意

    给定一个只含RGB三种字符的字符串,问最少修改多少个字符,能使得修改后的字符串存在一个长度为(k)的子串是...RGBRGB...这个循环字符串的子串。

    分析

    • 只含有3种字符,考虑从...RGBRGB...这个循环字符串大力枚举。
    • 子串要和这个循环字符串匹配只有三种情况,即开头是RGB,GBR和BRG。
    • 预处理出这三种匹配的字符匹配个数的前缀和,然后可以O(1)求出长度为k的子串对应这种匹配需要修改多少个字符,取最小值即可。

    代码

    #include <bits/stdc++.h>
    using namespace std;
    const int N=2e5+50;
    int q,n,k;
    char s[N];
    int dp[N][3];
    char to(int x){
        if(x==0){
            return 'R';
        }else if(x==1){
            return 'G';
        }else{
            return 'B';
        }
    }
    int main(void){
    //    freopen("in.txt","r",stdin);
        scanf("%d",&q);
        while(q--){
            scanf("%d%d",&n,&k);
            scanf("%s",s+1);
            //计算三种模式匹配下,到第i位匹配字符个数的前缀
            for(int i=0;i<=n;i++){
                dp[i][0]=dp[i][1]=dp[i][2]=0;
            }
            for(int i=0;i<3;i++){
                for(int j=1;j<=n;j++){
                    dp[j][i]=dp[j-1][i];
                    if(to((i+j-1+3)%3)==s[j]){
                        dp[j][i]++;
                    }
                }
            }
            int ans=0x3f3f3f3f;
            for(int i=0;i<3;i++){
                for(int j=1;j+k-1<=n;j++){
                    ans=min(ans,k-(dp[j+k-1][i]-dp[j-1][i]));
                }
            }
            printf("%d
    ",ans);
        }
        return 0;
    }
    

    F K-th Path

    题意

    给一个带权简单无向图,求第k小的最短路。

    分析

    • k范围很小。

    • 所求的最短路只可能出现两种情况:

      • 只含一条边的前k短路。
      • 由只含一条边的前k短路组成的最短路。
    • 因此取出前k小边,离散化后跑floyd,再排序取第k小最短路径。

    • 注意,但只含一条边的前k短路不止k条(比如相同的边就有k+1条,边权为x),选择哪一条进行floyd关系不大,简单证明:

      • 如果答案是由一条边组成的,选哪一条答案都一样是x。
      • 如果答案由多条边组成,那么答案肯定小于x,因为单条边的x就不止k个了,而小于x的又由多条边组成的,那么肯定是由小于x的单条边来组成,和x相同的边没有关系。

    代码

    #include <bits/stdc++.h>
    using namespace std;
    const int N=2e5+50;
    //400条边离散化会有800个点
    const int M=1005;
    typedef long long ll;
    struct es{
        int u,v,w;
        bool operator <(const es& rhs)const{
            return w<rhs.w;
        }
    }es[N];
    int n,m,k;
    map<int,int> mp;
    ll dis[M][M];
    int main(void){
    //    freopen("in.txt","r",stdin);
        scanf("%d%d%d",&n,&m,&k);
        for(int i=1;i<=m;i++){
            scanf("%d%d%d",&es[i].u,&es[i].v,&es[i].w);
        }
        sort(es+1,es+1+m);
        //取出前k小的边
        for(int i=1;i<M;i++){
            for(int j=1;j<M;j++){
                dis[i][j]=dis[j][i]=1e18;
                if(i==j){
                    dis[i][j]=0;
                }
            }
        }
        int cnt=0;
        for(int i=1;i<=k;i++){
            if(mp.count(es[i].u)==0){
                mp[es[i].u]=++cnt;
            }
            if(mp.count(es[i].v)==0){
                mp[es[i].v]=++cnt;
            }
            dis[mp[es[i].u]][mp[es[i].v]]=dis[mp[es[i].v]][mp[es[i].u]]=1ll*es[i].w;
        }
        for(int a=1;a<=cnt;a++){
            for(int i=1;i<=cnt;i++){
                for(int j=1;j<=cnt;j++){
                    dis[i][j]=min(dis[i][j],dis[i][a]+dis[a][j]);
                }
            }
        }
        vector<ll> ans;
        for(int i=1;i<=cnt;i++){
            for(int j=i+1;j<=cnt;j++){
                ans.push_back(dis[i][j]);
            }
        }
        sort(ans.begin(),ans.end());
        printf("%lld
    ",ans[k-1]);
        return 0;
    }
    
  • 相关阅读:
    函数function
    文件操作
    手机抓包app在python中使用
    手机app抓包工具,安卓手机adb无线连接
    selenium+options配置文件
    scrapy 执行同个项目多个爬虫
    最简单的???ubuntu 通过crontab定时执行一个程序
    scrapycrawl 爬取笔趣阁小说
    python装饰器见解笔记
    有关于python内置函数exec和eval一些见解笔记
  • 原文地址:https://www.cnblogs.com/zxcoder/p/11311960.html
Copyright © 2011-2022 走看看