【C++周报】第一期2021-8-1
【C++周报】第一期 2021-8-1
这一期我们来看这道题目:https://vijos.org/p/1058
这道题是一道非常好的模拟题。题目如下:
描述
我们用文本处理器来处理一个特殊的文本文件,该文本文件共有N行文本,每一行文本仅包含一个自然数,第一行为1、第二行为2,以此类推至N行为自然数N。
假设对该文本文件执行一次“剪切和粘贴”操作含义如下:首先选定连续的若干行文本,“剪切”操作将选定的文本从文件中剪下,而“粘贴”操作将剪切下来的文本插入到文件中的其他地方。
编写一个程序求出在进行了连续若干次“剪切和粘贴”操作后,文本文件中前十行的内容。
格式
输入格式
输入的第一行包含两个用空格隔开的自然数N和K,N表示文件的总行数(10≤N≤100,000),K表示“剪切和粘贴”的总次数(1≤k≤1000)。
下面K行每一行包含一次“剪切和粘贴”操作的执行信息,每行包含三个用空格隔开自然数A,B和C,其中1≤A≤B≤N,0≤C≤N-(B-A+1)。A和B表示选定文本的第一行和最后一行,C表示被剪切下来的文本待插入处的前一行,如果C等于0则被剪切下来的的文本将被插入到文件的开头。
输出格式
输出将由十行组成,其中包含所有的操作都完成后的文本文件中前十行所包含的数字。
我们来分析题意。整个剪切粘贴的过程可以分为如下几步:
第一步,把文本放进缓存区。
第二步,把已经剪切掉的部分后面的东西前移上去。
第三步,把要粘贴的地方所有后面的文本后移,腾出位子留给要粘贴的文本。
第四步,把缓存区上的文本粘贴进去。
那么,如何进行文本的复制操作呢?如果手动使用for循环,比较麻烦,并且需要注意是从前往后还是从后往前。(把前面的东西复制到后面去,避免数据覆盖,需要从后往前复制,而把后面的复制到前面的反之)
因此,我们可以使用一个函数,memmove!它会自动判断内存重叠的位置,并且自动判断从前往后还是从后往前。我们使用memmove,不仅可以少写几行代码(这个才是主要目的),并且正确性完全得到保证。
我们开始正式写代码。为了计算方便,我们可以定义临时变量len存放从a到b的长度。
#include<bits/stdc++.h> using namespace std; const int maxn=100010; int text[maxn],temp[maxn]; int n,k,a,b,c; int main(){ cin>>n>>k; for(int i=1;i<=n;i++)text[i]=i; for(int i=0;i<k;i++){ cin>>a>>b>>c; int len=b-a+1; memmove(temp,text+a,sizeof(int)*len);//待粘贴数字 memmove(text+a,text+b+1,sizeof(int)*(n-b));//把数字剪切掉 memmove(text+c+len+1,text+c+1,sizeof(int)*(n-len-c));//粘贴位置数字后移 memmove(text+c+1,temp,sizeof(int)*len);//粘贴进去 } for(int i=1;i<=10;i++)cout<<text[i]<<endl; return 0; }
完成!