[2020多校聯考]糖果機器
阿新 • • 發佈:2020-11-30
Solution
思路太妙,我想不到
一個位置的機器人能及時到達另一個位置去接糖果,當且僅當位置之差小於等於時間差,從 \(i\) 走到 \(j\) 用符號表示為
\[T_j-T_i\geq |S_j-S_i| \]把絕對值拆掉
\[\begin{cases} T_j-T_i\geq S_j-S_i\\ T_j-T_i\geq S_i-S_j\ \end{cases}\]再移項,把 \(i\) 和 \(j\) 分別移到其中一邊
\[\begin{cases} T_j-S_j\geq T_i-S_i\\ T_j+S_j\geq T_i+S_i\ \end{cases}\]將兩邊看成一個整體,將 \(T_x-S_x\)
#include<stdio.h> #include<algorithm> using namespace std; #define N 100007 inline int read(){ int x=0,flag=1; char c=getchar(); while(c<'0'||c>'9'){if(c=='-') flag=0;c=getchar();} while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+c-48;c=getchar();} return flag? x:-x; } struct Node{ int pos,t; int x,y; bool operator <(const Node X) const { if(x==X.x) return y<X.y; return x<X.x; } }a[N]; int n,top=0,tag[N],sta[N]; int main(){ freopen("candy.in","r",stdin); freopen("candy.out","w",stdout); n=read(); for(int i=1;i<=n;i++){ a[i].pos=read(),a[i].t=read(); a[i].x=a[i].t+a[i].pos,a[i].y=a[i].t-a[i].pos; } sort(a+1,a+1+n); sta[++top]=a[1].y,tag[1]=1; for(int i=2;i<=n;i++){ if(sta[top]>a[i].y){ sta[++top]=a[i].y; tag[i]=top; }else{ int l=1,r=top,ret=0; while(l<=r){ int mid=(l+r)>>1; if(sta[mid]<=a[i].y){ r=mid-1; ret=mid; }else l=mid+1; } if(!ret) ret=1; tag[i]=ret,sta[ret]=a[i].y; } } printf("%d\n",top); for(int i=1;i<=n;i++) printf("%d %d %d\n",a[i].pos,a[i].t,tag[i]); } /* 5 1 1 2 3 1 5 3 4 2 6 */
Tips
至於縱座標為什麼也要升序,可以考慮在橫座標相等的情況下,縱座標小的可以轉移到縱座標大的,反之不行,所以升序更優。