有效地计数线段

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):-

中的算法
  1. 在vector
  2. 中存储元组(i,time[i])
  3. 根据时间对矢量进行排序[i]
  4. 维护一个布尔数组来检查是否占用了一个plot。
  5. taken[i] = false
  6. 开始按顺序构建地块
  7. 初始森林= 1
  8. 当一个图被构造时,检查布尔数组中相邻的图。
  9. 如果两者都被占用,则森林=森林- 1
  10. 如果一个已被占用,则不更改
  11. 如果两者都是空森林=森林+ 1
  12. 每次施工后检查森林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提出的算法:)