Nothing for nothing ( 八 )

题目:[The Smallest String Concatenation]

(http://codeforces.com/problemset/problem/632/C)
题意:就是给你n个字符串,每个字符串长度不超过50,问你把这些字符串拼接在一起使它的字典序最小。
思路:一开始就以为是一个普通的字符串排序,利用sort的重载,后来发现存在一些问题,就是当字符串为x, xxa, xxz,的时候排序结果跟样例不一样后来发现,当某个串为另一个串的子串的时候会出现问题。所以就想到在sort的重载改一下条件,把两个字符串拼接在一起。
代码:

#include<bits/stdc++.h>
using namespace std;
const int maxn = 5*1e4+10;
bool cmp(string a, string b){//重载排序
     return a+b < b+a;//拼接的方法
}
string a[maxn];
int main(){
    int n;
    ios::sync_with_stdio(false);
    cin>>n;
    for(int i = 0; i < n; i++){
        cin>>a[i];
    }
    sort(a, a+n, cmp);
    for(int i = 0; i < n; i++){
        cout<<a[i];
    }
    cout<<endl;
return 0;
}

题目:Longest k-Good Segment

题意:给你一个长度为n的字符串,然后让你求出不大于k个不同的数的区间范围l和r。
思路:通过双端队列去维护,用vis数组标记这个数在不在双端队列中,用cn来记录双端队列中不同数的个数。
代码:

#include<bits/stdc++.h>
using namespace std;

const int maxn = 1e6+10;
int vis[maxn], a[maxn];
deque<int>q;
int main()
{
    int n, k;
    scanf("%d %d", &n, &k);
    for(int i = 0; i < n; i++)scanf("%d", &a[i]);
    while(q.size())q.pop_back();
    int ans = 0, l, r, cn = 0;
    memset(vis, 0, sizeof(vis));
    for(int i = 0; i < n; i++)
    {
        if(!vis[a[i]])cn++;//如果没有被标记过,不同数的个数加1
        vis[a[i]]++;//标记一下
        q.push_back(i);
        while(q.size() && cn > k)//如果不同数的个数大于k弹出队首的数
        {
            int t = q.front();
            vis[a[t]]--;
            if(!vis[a[t]])cn--;//如果这个数所有标记的都清空了,那么cn--;
            q.pop_front();
        }
        if(q.size() && ans < i-q.front()+1)//更新最大范围
        {
            ans = i-q.front()+1;
            l = q.front()+1;//因为从0开始的所以l, r加1
            r = i+1;
        }
    }
    printf("%d %d\n", l, r);

    return 0;
}

题目:Mr. Kitayuta’s Colorful Graph

题意:本题的题意就是给你一个无向图,n个点, m条边,然后路径是ai–bi,路的颜色是wi.
然后经过q次查询,问你ui—vi这条边之间间接或者直接有多少中颜色,每一种路颜色必须一样。
思路:dfs+暴力
代码:

#include<bits/stdc++.h>
using namespace std;
const int maxn = 1000;
int ne[maxn], e[maxn], h[maxn], w[maxn], tot = 0;
int vis[maxn], flag[maxn], ans = 0, res = 0;
void add(int u, int v, int val)//链式前向星存图
{
    e[tot] = v;
    w[tot] = val;
    ne[tot] = h[u];
    h[u] = tot++;
}

void dfs(int u, int v, int val)//u是起点,v是重点,val是路的颜色。
{
    if(u == v)
    {
        ans = 1;
        return;
    }
    vis[u] = 1;
    for(int i = h[u]; ~i; i = ne[i])
    {
        int t = e[i];
        if(!vis[t] && w[i] == val)
        {
            vis[t] = 1;
            dfs(t, v, val);
            vis[t] = 1;
        }
    }
}
int main()
{
    int n, m;
    scanf("%d %d", &n, &m);
    memset(h, -1, sizeof(h));
    for(int i = 0; i < m; i++)
    {
        int u, v, w;
        scanf("%d %d %d", &u, &v, &w);
        add(u, v, w);
        add(v, u, w);
    }
    int q, u, v;
    scanf("%d", &q);
    for(int i = 0; i < q; i++)
    {
        res = 0;
        scanf("%d %d", &u, &v);
        memset(flag, 0, sizeof(flag));//用来保存该颜色是否已经存在
        for(int j = h[u]; ~j; j = ne[j])
        {
            ans = 0;
            memset(vis, 0, sizeof(vis));

            dfs(u, v, w[j]);
            if(flag[w[j]])continue;
            res += ans;
            flag[w[j]] = 1;
        }
        cout<<res<<endl;

    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值