Nothing for Nothing(二十)

本文精选三道算法竞赛题目,包括图论、字符串处理及排序算法的深入解析。通过并查集解决NewReform问题,寻找有向图中孤立节点的最小数量;采用二分搜索策略解决EnduringExodus问题,优化羊群安置方案;利用线段树技术解答XeniaandBitOperations问题,高效处理位运算。最后,通过巧妙的排序与更新策略,提供Report问题的解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目:New Reform

题意:就是给你一个无向图,如果要把无向图改为有向图,怎么改使孤立节点最少,输出孤立节点的个数,孤立节点没有入度的点都是孤立节点。
思路:在一个联通块里面,如果不存在环的话,只有一个孤立的节点,如果存在环的话那么就没有孤立的节点,所以我们就用并查集去实现,是否存在环。如何判定呢,如果这两个点已经在一个联通块里面,那么这个联通块里面就存在环。
代码:

#include<stdio.h>
#include<iostream>
#include<stack>
#include<string.h>
#include<algorithm>
using namespace std;
const int maxn = 1e5+10;
const int N = 50010;
int fa[maxn];
bool vis[maxn];
int Find(int x)
{
    if(x == fa[x])return x;
    return fa[x]=Find(fa[x]);
}
int n, m, u, v;
int main(){
    scanf("%d %d", &n, &m);
    for(int i = 1; i <= n; i++)fa[i] = i;
    for(int i = 1; i <= m; i++){
        scanf("%d %d", &u, &v);
        int xx = Find(u);
        int yy = Find(v);
        if(xx == yy){//存在环
            vis[xx] = 1;
        }
        else {
            fa[yy] = xx;
            if(vis[yy])vis[xx] = vis[yy];//如果yy中存在环,那么整个一定存在环

        }
    }
    int cnt = 0;
    for(int i = 1; i <= n; i++){//遍历一下
        if(Find(i) == i && !vis[i])cnt++;
    }
    printf("%d\n", cnt);

return 0;
}


题目:Enduring Exodus

题意:给你一行0,1组成的字符串,1代表这个房间已经住满了,0代表这个房间还可以住人,一个人带着他的k头羊,怎么安排使羊距离这个人的距离最近,输出这个结果。
思路:这道题采用二分,二分去遍历距离,如果这个距离满足k+1空间那么这个距离就是OK的,找到最小的一个符合要求的。
代码:

#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e5+10;
int sum[maxn];
char a[maxn];
int n, m;
inline int check(int pos, int mid){
       int l = max(1, pos-mid);
       int r = min(n, pos+mid);
       return (sum[r]-sum[l-1]-1) >= m;
}
inline int Bsearch(int pos, int l, int r){
       while(l < r){
         int mid = (l+r)>>1;
         if(check(pos, mid))r = mid;
         else l = mid+1;
       }
       return l;
}
int main(){
    scanf("%d %d", &n, &m);
    scanf("%s", a+1);
    sum[0] = 0;
    for(int i = 1; i <= n; i++){
       sum[i] = sum[i-1] + (a[i] == '0');
    }
    int l = 1, r = n;
    int ans = INT_MAX;
    for(int i = 1; i <= n; i++){
        l = 1, r = n;
        if(a[i] == '0'){
            ans = min(Bsearch(i, l, r), ans);
        }
    }
    printf("%d\n", ans);

return 0;
}

题目:Xenia and Bit Operations

参考博客:CodeForces 339D Xenia and Bit Operations (线段树)
代码:

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

const int maxn = 200005;

int st[maxn<<2];
void pushup(int o, int ok){
     if(ok) st[o] = st[o<<1|1]|st[o<<1];
     else st[o] = st[o<<1|1]^st[o<<1];
}

void build(int o, int l, int r, int ok)
{
    if(l == r)scanf("%d", &st[o]);
    else
    {
        int m = l + ((r-l)>>1);
        build(o<<1, l, m, !ok);
        build(o<<1|1, m+1, r, !ok);
        pushup(o, ok);
    }
}
void update(int o, int l, int r, int ind, int ans, int ok)
{
    if(l == r)
    {
        st[o] = ans;
        return;
    }
    int m = l + ((r-l)>>1);
    if(ind <= m)update(o<<1, l, m, ind, ans, !ok);
    else update(o<<1|1, m+1, r, ind, ans, !ok);
    pushup(o, ok);
}

int main()
{
    int n, m;
    scanf("%d %d", &n, &m);
    int ok = (n&1);
    n = (1<<n);
    build(1,1,n, ok);
    while(m--){
        int p, b;
        scanf("%d %d", &p, &b);
        update(1, 1, n, p, b, ok);
        printf("%d\n", st[1]);
    }
}


题目:Report

题意:给你一个字符串,m个操作,ti,ri代表从1到ri进行从大道小的顺序或者从小到达的顺序,输出最后的顺序。
思路:暴力指定是行不通,所以只能找找规律换换思路,通过各种操作你会发现ri最大值之前的所有操作都是无效,所以我们的操作只在ri之后的有效,找到最大的ri之后你还想着暴力,那么一定会超时,所以只能再想办法优化了,看代码。
代码:

#include<bits/stdc++.h>
using namespace std;
int main(){
    int n, m, t, x, y;
    scanf("%d %d", &n, &m);
    vector<int>a, op(n+2, 0), pos(n+2, 0);
    for(int i = 1; i <= n; i++){
        scanf("%d", &t);
        a.push_back(t);
    }
    int maxx = 0;
    vector<int> res = a, v = a;
    for(int i = 1; i <= m; i++){
        scanf("%d %d", &x, &y);
        op[y-1] = x;
        pos[y-1] = i;
        maxx = max(maxx, y);
    }
    sort(v.begin(), v.begin()+maxx);
    for(int i = maxx-1; i >= 0; i--){
        if(pos[i] < pos[i+1]){
            pos[i] = pos[i+1];
            op[i] = op[i+1];
        }
    }
    int l = 0, r = maxx-1;
    for(int i = maxx-1; i >= 0; i--){
        if(op[i] == 2)res[i] = v[l++];
        else res[i] = v[r--];
    }
    for(int i = 0; i < res.size(); i++){
        if(i != 0)printf(" ");
        printf("%d", res[i]);
    }
    printf("\n");

return 0;
}

### 关于 'Nothing to be done for' 的含义 在编程和构建系统中,“Nothing to be done for”通常是由工具(如 `Make` 或类似的构建工具)发出的消息。它表示目标文件已经是最新状态,无需重新编译或执行任何操作[^3]。 当构建系统运行时,它会比较源文件的时间戳与目标文件的时间戳。如果目标文件已经存在,并且其时间戳比所有依赖项更新,则不会触发任何进一步的操作。这种行为是为了优化构建过程,避免不必要的重复工作[^4]。 以下是可能的原因及其解释: 1. **目标已是最新的** 如果构建系统的配置文件(例如 Makefile 中的目标定义)表明当前目标不需要更改,因为它的依赖项未发生变化,那么会出现此消息。这意味着所有的依赖都已经被处理完毕,或者根本没有变化需要处理[^5]。 2. **无有效规则匹配** 另一种可能性是,在某些情况下,指定的目标没有任何适用的规则来完成所需的任务。这可能是由于错误的路径、名称拼写错误或其他配置问题引起的[^6]。 #### 解决方法 为了排查并解决问题,可以采取以下措施: - **检查依赖关系**:确认 Makefile 或其他构建脚本中的依赖关系是否正确设置。确保所有必要的输入文件都被正确定义为依赖项。 - **强制重建**:通过删除旧的目标文件或将它们标记为过期,强迫系统重新生成这些文件。例如,在 GNU Make 中可以使用 `-B` 参数强制全部重做[^7]。 - **调试模式启用**:许多现代构建工具有内置的日志功能可以帮助诊断为什么某个特定任务被认为已完成而跳过了实际的工作流。尝试开启更详细的日志记录选项以便更好地理解内部逻辑流程[^8]。 ```makefile # Example of forcing rebuild with GNU make $ make -B target_name ``` 上述命令将忽略现有的时间戳差异,从而强制重新创建指定的目标。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值