有效地计数线段
Counting line segments efficiently
本文关键字:有效地 更新时间:2023-10-16
我正在尝试解决澳大利亚信息学培训网站上的切片天堂。其思想是,您有一个区块序列(实际上是语句中的forest,我的代码中的land
),并且每次删除一个区块(或转换为度假村),这可能会增加或减少连续(forest)区块的运行次数。我要计算历史上最大的运行次数。输入是块的数量N,后面是N行,表示每个块的移除时间。时间是从1开始的连续整数。
我的代码工作得很好(我认为),但是对于一些较大的情况来说太慢了。有人能建议一个简单的快速工作的解决方案,请,或任何改进,可以作出我,使其运行在O(N)?
<标题>慢解#include <cstdio>
FILE* infile;
FILE* outfile;
int N,c,j,l,best;
int main(){
infile=fopen("slicein.txt","r");
outfile=fopen("sliceout.txt","w");
fscanf(infile,"%dn",&N);
int land[N+1];
int location[N+1];
for (int i=1;i<=N;i++){
fscanf(infile,"%dn",&location[i]);
land[i]=0;
}
j=1;l=1;c=1;
for (int i=1;i<=N;i++){
if (location[i]==j){
land[i]=1;
if (land[i+1]!=1 && land[i-1]!=1 && i!=N && i!=1) c++;
else if (land[i-1]==1 && land[i+1]==1 && i!=N && i!=1) c--;
j++;
if (c>best) best=c;
i=0;
}
if (i==N && l!=N*N){
i=0;
}
else if (l==N*N) break;
l++;
}
fprintf(outfile,"%dn",best);
fclose(infile);
fclose(outfile);
return 0;
}
标题>
你的问题是,你基本上有两个嵌套循环,一个外部的j
和一个内部的i
,虽然你没有明确地写它。这为您提供了一个O(N)方法来查找当前位置,这相当于O(N2)的总成本。
基本信息是,在每一轮j
中,您需要找到i
在该轮中转换的位置。您可以在读取输入时为此构建一个映射。将location
作为从位置到时间的映射,改为从时间到位置的映射:
for (int i=1;i<=N;i++){
int t;
fscanf(infile,"%dn",&t);
location[t] = i;
land[i]=0;
}
那么你可以凑合用一个O(N)循环,一切都应该没问题。请确保索引正确,因为您似乎在某些地方使用基于1的索引,而在其他地方使用基于0的索引。
无法找出您的解决方案,但以下是在O(nlogn):-
中的算法
- 在vector
中存储元组(i,time[i])- 根据时间对矢量进行排序[i]
- 维护一个布尔数组来检查是否占用了一个plot。
- taken[i] = false
- 开始按顺序构建地块
- 初始森林= 1
- 当一个图被构造时,检查布尔数组中相邻的图。
- 如果两者都被占用,则森林=森林- 1
- 如果一个已被占用,则不更改
- 如果两者都是空森林=森林+ 1
- 每次施工后检查森林id是否大于最大计数。
时间复杂度:
Sorting takes O(logn)
plot construction in sorted order O(n)
感兴趣的人可以看看我的答案:
#include <cstdio>
FILE* infile;
FILE* outfile;
int N,c,j,l,b,best;
int main(){
infile=fopen("slicein.txt","r");
outfile=fopen("sliceout.txt","w");
fscanf(infile,"%dn",&N);
int land[N+1];
int location[N+1];
j=1;l=1;c=1;b=1;
for (int i=1;i<=N;i++){
int t;
fscanf(infile,"%dn",&t);
location[t]=i;
land[i]=0;
}
for (int i=1;i<=N;i++){
land[location[i]]=1;
if (land[location[i]-1]!=1 && land[location[i]+1]!=1 && location[i]!=1 && location[i]!=N) c++;
else if (land[location[i]-1]==1 && land[location[i]+1]==1 && location[i]!=1 && location[i]!=N) c--;
else if (land[location[i]-1]==1 && location[i]==N) c--;
else if (land[location[i]+1]==1 && location[i]==1) c--;
if (c>best) best=c;
}
fprintf(outfile,"%dn",best);
fclose(infile);
fclose(outfile);
return 0;}
感谢MvG提出的算法:)
相关文章:
- 有效地使用std::unordered_map来插入或增加键的值
- 如何有效地在 std::vector 中插入一对?
- 有效地计算多维数组的累积和?
- 如何有效地计算将单位立方体映射到自身的反射和旋转?
- 有效地将大数存储为 2 的幂用于路径问题
- 如何在C++中写入 1000 个文件时有效地缓冲
- 如何有效地找到数组中三元组和的最小差异?
- 如何在C++中有效地将数字值重新分配给字符数组
- C++有效地找到向量中第一个最接近的匹配值?
- 如何有效地操作满足给定谓词的向量中的所有项目?
- 有效地将数据加载到 std::vector 中<char>
- 如何在使用 cin 请求 int 时有效地使用户输入万无一失?
- C++:有效地将Sha256摘要放入OpenSSL Bignum?
- 如何有效地收集给定数组中的重复元素?
- 如何有效地修剪和合并四叉树中的节点?
- 可以有效地转换 std::any 与 std::any_cast
- 只需要知道我在c ++中打印模式的方式是否有效,或者有另一种方法可以有效地做到这一点
- 如何使用包含内部类的类实例有效地从内部类访问成员?
- 当表示为对象的一维向量时,有效地旋转 NxM 矩阵 (C++)
- 我们怎样才能有效地压缩DNA串