题目:
长为整数L(1<=L<=10000)的马路,在每个整数坐标点有一棵树,即在0,1,2,...,L共L+1个位置上有L+1棵树。要移走某区间内的树,如 100 200表示移走从100到200之间(包括端点)的树。有M(1<=M<=100)个区间,区间之间可能重叠。求剩下的树的个数。
思路:
离散的区间合并问题,可以用标记法:即把域内的整数都初始标记为0,有区间括起来的整数标为1,则剩下的即为没在区间内的。
#include <iostream>
#include <stdio.h>
#include <cstring>
using namespace std;
int L,M,n;
int A[10002];
int main(){
int a,b;
int i,j;
while(scanf("%d %d",&L,&M)!=EOF){ //输入L,M
n=0;
memset(A,0,10002*sizeof(int)); //初始化标记为0
for(i=0;i<M;i++){ //输入区间
scanf("%d %d",&a,&b);
for(j=a;j<=b;j++) //把该区间的标记都改为1
A[j]=1;
}
for(i=0;i<=L;i++){ //计算剩下的树(即标记为0)
if(A[i]==0)
n++;
}
printf("%d\n",n); //输出结果
}
return 0;
}
刚开始做复杂了,用数组模拟出区间,然后再一一输入区间,有交集的区间合并。最后再算区间外的数。从代码长度即可知复杂得多(另:该方法在九度上刷不过,但在牛客上没问题,很是纳闷)。
#include <iostream>
#include <stdio.h>
using namespace std;
int L,M,n;
int A[102],B[102];
//处理新区间与原区间
void doInterval(int a,int b);
//判断一个整数在区间集中的位置
bool isIn(int a,int &ia);
//把j开始的区间,都往前挪k位
void moveInternal(int j,int k);
int main(){
int a,b;
int i;
while(scanf("%d %d",&L,&M)!=EOF){ //输入L,M
n=0;
if((L<1 || L>10000)||(M<1 || M>100))
continue;
for(i=0;i<M;i++){ //输入区间,归并
scanf("%d %d",&a,&b);
if(a>b){
a=a^b; b=a^b; a=a^b;
}
doInterval(a,b);
}
for(L=L+1,i=0;i<n;i++){ //计算剩下的树
L=L-(B[i]-A[i]+1);
}
printf("%d\n",L); //输出结果
}
return 0;
}
//处理新区间与原区间
void doInterval(int a,int b){
int i=0;
int ia,ib;
bool ina,inb;
ina=isIn(a,ia); //判断a的位置
inb=isIn(b,ib); //判断b的位置
if(ina){ //a在区间内
if(inb) //b在区间内
B[ia]=B[ib];
else //b在空档
B[ia]=b;
moveInternal(ib+1,ib-ia);
n=n-(ib-ia);
}
else{ //a在空档
if(inb){ //b在区间内
A[ia+1]=a;
B[ia+1]=B[ib];
moveInternal(ib+1,ib-ia-1);
n=n-(ib-ia-1);
}
else{ //b在空档
if(ia==ib){ //a,b在同一空档
moveInternal(ia+1,-1);
A[ia+1]=a;
B[ia+1]=b;
n++;
}
else{ //a,b不在同一空档
A[ia+1]=a;
B[ia+1]=b;
moveInternal(ib+1,ib-ia-1);
n=n-(ib-ia-1);
}
}
}
}
//判断一个整数在区间集中的位置
bool isIn(int a,int &ia){
bool in=true;
int i=0;
while(i<n){
if(A[i]<=a)
i++;
else
break;
}
//a在区间内
if((i!=0 && i<n && a<=B[i-1])||(i!=0 && i==n && a<=B[n-1])){
ia=i-1; //a在第ia个区间内
}
else{ //a在空档
ia=i-1; //a在第ia个区间后的空档
in=false;
}
return in;
}
//把j开始的区间,都往前挪k位
void moveInternal(int j,int k){
int i;
for(i=j;i<n;i++){
A[i-k]=A[i];
B[i-k]=B[i];
}
}