https://acm.hdu.edu.cn/showproblem.php?pid=6976
题意:
有n条直线,Alice和Bob玩n次游戏
第i次游戏Alice先选i条直线,Bob再画任意一条直线
Bob的罚分为与画的直线相交的被选中的直线数
Alice想让罚分尽可能大,Bob想让罚分尽可能小
求每次游戏的罚分
对于Alice的一种选法,Bob肯定是画一条斜率为出现次数最多的斜率的直线
因为只有平行才不相交
所以Alice要最小化出现次数最多的斜率的最大值
所以就依次从每种斜率选1个,都选了1个之后再选第2个……
#include<bits/stdc++.h> using namespace std; #define N 100001 double k[N]; int sum[N]; const double eps=1e-11; int main() { int T,n,x1,y1,x2,y2,m,mi; scanf("%d",&T); while(T--) { scanf("%d",&n); for(int i=1;i<=n;++i) { scanf("%d%d%d%d",&x1,&y1,&x2,&y2); if(x1!=x2) k[i]=1.0*(y1-y2)/(x1-x2); else k[i]=1e10; } sort(k+1,k+n+1); for(int i=1;i<=n;++i) sum[i]=0; m=1; sum[1]=1; for(int i=2;i<=n;++i) if(k[i]-k[i-1]<eps) sum[m]++; else sum[++m]=1; sort(sum+1,sum+m+1); // for(int i=1;i<=tmp;++i) tmp[i]=sum[i]; // int mm=unique(tmp+1,tmp+m+1)-tmp-1; int now=1,lev=1,last=1; for(int i=1;i<=n;++i) { printf("%d ",i-lev); ++now; if(now>m) { ++lev; now=last; while(sum[now]<lev) ++now; last=now; } } } }