【QWQ】第二问几乎全WA求调【QWQ】】
查看原帖
【QWQ】第二问几乎全WA求调【QWQ】】
393852
C83_AD楼主2024/11/26 17:52

压缩包里的样例数据过不了,摆了,交上去20分【QWQ】

我的思路:
首先,可以求出每个车超速的闭区间(以下称“区间”)。由于测速器只在整数位置存在,所以区间取整。
然后,将这些区间映射到测速点(即以测速点编号作为边界/内容)。
这是因为:测速点保证严格单调递增,其间距离不影响问题结果,可以处理为1,来方便、统一地处理离散的数据。
具体而言:
每一个区间,对测速点数据,二分寻其左边界址或其大于情况,寻其右边界址及或小于情况,以此为据,更新区间
这一预处理过程时间复杂度O(nlogm) 分析两问:
1、枚举每一个区间【O(n)】,不为空则被记超速。
2、前面的操作将问题转化为一个非常经典的贪心问题:
1~m间,给定n个区间。若选定x个整数,使得每一区间至少包含这些整数的某一个,求x的最小值
思路:希望取点尽可能少,那么应当尽可能选择区间交点。容易想到,若二区间存在交集,必然有一区间右端点在交集上。
算法:
将所有区间右端点排序【O(nlogn)】,然后依次从左到右扫描每一个非空区间【O(nm)。这是理论最坏情况,实际上接近O(n)】。 若直到其右端点仍然不包含已选定的整数,选定右端点。
否则,忽略此区间。

总体时间复杂度:O(nm)。

代码:

#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;

struct cint{//each car 
	int l,r;//left or right side
}car[100003];
/*tool*/void deal(int i,int di,int vi,int ai);//input car i
/*tool*/bool cmp(cint a,cint b);//to judge if a should be put before b

int ver[100003];//ce shu dian
bool flag[100003];//to sigh if ver[i] is chosen
/*tool*/int find_eorup(int x);//  "equal or less" (for x)in ver
/*tool*/int find_eorlo(int x);//"equal or greater"(for x)in ver

void slove();//sloving prosess
int n,m,l,v,di,vi,ai,t,t1,t2;//other figures would be used
int ans1,ans2;//answers

int main(){
	scanf("%d",&t);
	while(t--) slove();
	return 0;
}
void slove(){
	//inputs
	scanf("%d%d%d%d",&n,&m,&l,&v);
	for(int i=1;i<=n;++i){
		scanf("%d%d%d",&di,&vi,&ai);
		deal(i,di,vi,ai);
	}
	for(int i=1;i<=m;++i) scanf("%d",&ver[i]);
	//per-treatment
	for(int i=1;i<=n;++i){
		if(car[i].l>car[i].r) continue;
		car[i].l=find_eorup(car[i].l);
		car[i].r=find_eorlo(car[i].r);
	}
	//slove1
	ans1=0;
	for(int i=1;i<=n;++i) if(car[i].l<=car[i].r) ++ans1;
	//slove2
	ans2=0;
	memset(flag,sizeof(flag),0);
	sort(car+1,car+1+n,cmp);
	for(int i=1;i<=n;++i){
		if(car[i].l>car[i].r) continue;
		bool t_flag=true;
		for(int j=car[i].l;j<=car[i].r;++j) if(flag[j]){
			t_flag=false;
			break;
		}
		if(t_flag) flag[car[i].r]=true,++ans2; 
	}
	//output
	printf("%d %d\n",ans1,m-ans2);
}

//tools
void deal(int i,int di,int vi,int ai){
	if(ai==0){
		car[i].l=di;
		vi<=v?car[i].r=-1:
			  car[i].r= l;
	}
	else if(ai>0){
		car[i].r=l;
		vi>v ?car[i].l=di:
		vi==v?car[i].l=di+1:
		      car[i].l=di+(v*v-vi*vi)/(2*ai)+1;
	}
	else{
		if(vi<=v) car[i].r=-1;
		else{
			t1=vi*vi-v*v,t2=-2*ai;
			car[i].l=di;
			car[i].r=di+t1/t2-!(t1%t2);
		}
	}
}
int find_eorup(int x){//finding the first figure which is not less than x
	int l=1,r=m,mid;
	while(l<=r) (ver[mid=(l+r)/2]<x) ? (l=mid+1) : (r=mid-1);
	return l;
}
int find_eorlo(int x){//finding the last figure which is not greater than x
	int l=1,r=m,mid;
	while(l<=r) (ver[mid=(l+r)/2]>x) ? (r=mid-1) : (l=mid+1);
	return r;
}
bool cmp(cint a,cint b){//key:car[i].r
	return a.r<b.r;
}
2024/11/26 17:52
加载中...