ENDOR

link

\(O(N^2)\) 的做法比较简单,枚举两个小蜥蜴的相遇时间然后就可以把一只蜥蜴的路程划分成很多阶段,然后每个阶段的颜色可求,累计答案即可。

考虑到数据范围可以猜想需要使用 \(O(NK)\) 的算法,结合意义可以猜出这个算法应该是统计每只蜥蜴路程上每种颜色的路程长度然后累加输出,毕竟前面那种算法慢也就慢在这里。然后考虑如何用前一只蜥蜴的答案去更新后一只的即可,画个图就好啦。

又一次开了龙龙宝宝。

#include<bits/stdc++.h>
//#define feyn
#define int long long
const int N=100010;
const int M=50;
using namespace std;
inline void read(int &wh){
    wh=0;int f=1;char w=getchar();
    while(w<'0'||w>'9'){if(w=='-')f=-1;w=getchar();}
    while(w<='9'&&w>='0'){wh=wh*10+w-'0';w=getchar();}
    wh*=f;return;
}
inline bool get(){//向右爬行 
	char w=getchar();
	while(w!='D'&&w!='L')w=getchar();
	return w=='D';
}

int m,n,len;//len->总长度 
struct node{
	int a,b;//place&color
}a[N],b[N];
int x,y,ans[M];
inline bool cmp(node s1,node s2){
	return s1.a<s2.a;
}

int f[M],g[M];

int final_color;
inline void add(int wh){
	int now_len=a[wh].a-a[wh-1].a;
	final_color=(final_color+a[wh].b)%n;
	//printf("%lld %lld\n",now_len,final_color);
	for(int i=0;i<n;i++)g[i]=f[i];
	for(int i=0;i<n;i++)f[i]=g[(i-a[wh].b+n)%n];
	//for(int k=0;k<n;k++)printf("%lld ",f[k]);printf("\n");
	f[final_color]+=now_len;f[a[wh].b]+=now_len;
}

signed main(){
	
	#ifdef feyn
	freopen("in.txt","r",stdin);
	#endif
	
	read(m);read(n);read(len);
	for(int i=1;i<=m;i++){
		int s1,s2;read(s1);read(s2);
		if(get())a[++x]=(node){s1,s2};
		else b[++y]=(node){s1,s2};
	}
	sort(a+1,a+x+1,cmp);
	sort(b+1,b+y+1,cmp);
	for(int i=1;i<=x;i++){
		//向右的贡献 
		ans[a[i].b]+=(len-a[i].a)*2;
	}
	for(int i=1,j=1;i<=y;i++){
		while(j<=x&&a[j].a<=b[i].a)add(j++);
		for(int k=0;k<n;k++)ans[(k+b[i].b)%n]+=f[k];
		int now_len=b[i].a-a[j-1].a;
		ans[b[i].b]+=now_len;
		ans[(final_color+b[i].b)%n]+=now_len;
		//for(int k=0;k<n;k++)printf("%lld ",f[k]);printf("\n");
	}
	for(int i=0;i<n;i++)printf("%.1f\n",ans[i]/2.0);
	
	return 0;
}
posted @ 2022-07-21 11:21  Feyn618  阅读(67)  评论(0编辑  收藏  举报