[20200727NOIP提高组模拟T2]走路
题目大意:
今有一数轴,有若干人在其上走,从时间$begin$开使在$s$处出现,走到$t$处后下一秒消失,任何人速度均为$1$或$-1$,现请你求出任意一人可与多少人相遇.两人相遇,当且仅当他们同时同地存在,且任意两人至多相遇一次.
solution:
简单线性规划,以时间作为$x$轴,位置作为$y$轴,每人的行走状态可以用一线段表示.先将出现时间按从小到大排序,预处理每人速度.然后一一枚举两人,取出现时间交集,端点控制判断交集处线段是否相交即可.
code:
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<cstdlib> 5 #include<cmath> 6 #include<algorithm> 7 #include<queue> 8 #include<ctime> 9 #include<map> 10 #define R register 11 #define next exnttttttttt 12 #define debug puts("mlg") 13 using namespace std; 14 typedef long long ll; 15 typedef long double ld; 16 typedef unsigned long long ull; 17 inline ll read(); 18 inline void write(ll x); 19 inline void writesp(ll x); 20 inline void writeln(ll x); 21 ll n; 22 struct node{ 23 ll begin,end,s,t,v,name1;//name1为排序前的编号,begin为出现时间,end为走到终点时间,s为启动,t为终点,v为速度1/-1 24 bool operator <(const node X)const{return begin<X.begin;} 25 }pr[1100]; 26 ll ans[1100]; 27 inline bool check(ll i,ll j){ 28 if(pr[i].end<pr[j].begin) return false; 29 ll Beg=pr[j].begin,End=min(pr[i].end,pr[j].end); 30 ll Y1_beg=pr[i].s+pr[i].v*(Beg-pr[i].begin),Y2_beg=pr[j].s+pr[j].v*(Beg-pr[j].begin); 31 ll Y1_end=Y1_beg+(End-Beg)*pr[i].v,Y2_end=Y2_beg+(End-Beg)*pr[j].v; 32 return (Y1_beg-Y2_beg)*(Y1_end-Y2_end)<=0; 33 } 34 int main(){ 35 freopen("walk.in","r",stdin); 36 freopen("walk.out","w",stdout); 37 n=read(); 38 for(R ll i=1;i<=n;i++) pr[i].name1=i,pr[i].begin=read(),pr[i].s=read(),pr[i].t=read(),pr[i].end=pr[i].begin+abs(pr[i].t-pr[i].s),pr[i].v=(pr[i].s<pr[i].t?1:-1); 39 sort(pr+1,pr+n+1); 40 for(R ll i=1;i<=n;i++){ 41 for(R ll j=i+1;j<=n;j++){ 42 if(check(i,j)) ++ans[pr[i].name1],++ans[pr[j].name1]; 43 } 44 } 45 for(R ll i=1;i<=n;i++) writesp(ans[i]); 46 } 47 inline ll read(){ll x=0,t=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-') t=-1;ch=getchar();}while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}return x*t;} 48 inline void write(ll x){if(x<0){putchar('-');x=-x;}if(x<=9){putchar(x+'0');return;}write(x/10);putchar(x%10+'0');} 49 inline void writesp(ll x){write(x);putchar(' ');} 50 inline void writeln(ll x){write(x);putchar('\n');}