SRM 562 Div1 500 CheckerFreeness
2017-05-04 20:13
513 查看
/* 通过枚举一对黑点(l,r)。 我们可以计算出其他所有白点和他们的相对位置(用叉积表示) 我们把剩余的白点以和直线(l,r)的左右位置分成两部分 我们用pos表示在线段l -> r左侧的点,其相对于l,相对于r,分别是顺时针第pos[i].fr, pos[i].sc个点。 lim表示在l -> r右侧的点,与它,选中的l,r,能形成凸多边形的左侧点,需要满足fr >= lim[i].fr, sc <= lim[i].sc 然后我们对pos和lim进行排序 之后我们利用树状数组,把pos中fr>=lim[i].fr的不断sc加入树状数组后,如果从树状数组中找到了对于lim[i]合法的sc时就得到了答案 */ #include<bits/stdc++.h> #define cl(x) memset(x, 0, sizeof(x)); #define pii pair<int, int> #define fr first #define sc second #define M 250 typedef long long ll; using namespace std; int n,m; bool side[M]; // side[i] = 1,表示第i个点在线段l -> r的左侧 struct poi{ int x, y, id; poi(){} poi(int _x, int _y) { x = _x; y = _y; } poi operator + (const poi &b) { return poi(x + b.x, y + b.y); } poi operator - (const poi &b) { return poi(x - b.x, y - b.y); } ll operator * (const poi &b) { return 1ll * x * b.y - 1ll * y * b.x; } // 叉积 }W[M],B[M],tmp[M]; // 存白点相对于被选中的两个黑点的坐标; bool operator < (poi a, poi b) { return a * b < 0; } pii pos[M], lim[M]; //pos表示在线段l -> r左侧的点,其相对于l,相对于r,分别是顺时针第pos[i].fr, pos[i].sc个点。 //lim表示在l -> r右侧的点,与它,选中的l,r,能形成凸多边形的左侧点,需要满足fr >= lim[i].fr, sc <= lim[i].sc int c[M]; // 树状数组 void add(int x) { // 单点加 for (int i = x; i <= n; i += (i & (-i)))++c[i]; } int get(int x) { // 前缀和 int ret = 0; for (int i = x; i; i -= (i & (-i))) ret += c[i]; return ret; } bool cmp(const pii &a, const pii &b) { return a.fr == b.fr ? a.sc < b.sc : a.fr > b.fr; } bool check(poi l, poi r) { // 选择l,r两个黑点为对角上的黑点 int k = 0, p = 0; for (int i = 1; i <= n; ++i) side[i]=((W[i] - r) * (l - r) > 0ll); // 判断白点在两个黑点的哪一侧 for (int i = 1; i <= n; ++i) if (side[i]) tmp[++k] = W[i] - l, tmp[k].id = k; // 计算相对l的极角 sort(tmp + 1, tmp + k + 1); // 因为都在pi的范围内,所以可以直接用叉积来排序 for (int i = 1; i <= k; ++i) pos[tmp[i].id].fr = i; // 确定下相对l极角序的排名 for (int i = 1; i <= n; ++i) if (!side[i])lim[++p].fr = upper_bound(tmp + 1, tmp + k + 1, l - W[i]) - tmp; // 确定下对应的左侧点,相对l的极角序至少要排在第几位 k = 0; p = 0; // 同理计算相对r的极角序 for (int i = 1; i <= n; ++i) if (side[i]) tmp[++k] = W[i] - r, tmp[k].id = k; sort(tmp + 1, tmp + k + 1); for (int i = 1; i <= k; ++i) pos[tmp[i].id].sc = i; for (int i = 1; i <= n; ++i) if (!side[i])lim[++p].sc = lower_bound(tmp + 1, tmp + k + 1, r - W[i]) - tmp - 1; cl(c); sort(pos + 1, pos + k + 1, cmp); int tp = 1; sort(lim + 1, lim + p + 1, cmp); // 都根据两维关键字排序 for (int i = 1; i <= p; ++i) { while (tp <= k && pos[tp].fr >= lim[i].fr) // 把fr这维满足条件的左侧点加入树状数组的sc位置 add(pos[tp++].sc); if (get(lim[i].sc)) return 1; // 存在满足条件的点 }return 0; } int main(){ scanf("%d",&n); for (int i = 1; i <= n; ++i) scanf("%d",&W[i].x); for (int i = 1; i <= n; ++i) scanf("%d",&W[i].y); scanf("%d",&m); for (int i = 1; i <= m; ++i) scanf("%d",&B[i].x); for (int i = 1; i <= m; ++i) scanf("%d",&B[i].y); for (int i = 1; i <= m; ++i) for (int j = i + 1; j <= m; ++j) if (check(B[i], B[j])){puts("NO");return 0;} puts("YES"); return 0; }
相关文章推荐
- Topcoder SRM 663 Div2 Problem 500 - ABBA 解题报告
- SRM 559 Div1 500 HatRack
- SRM 669 DIV 2 CombiningSlimes 500-point
- SRM 497(DIVII) 500 PermutationSignature
- Topcoder SRM 660 DIV1 500 Privateparty(数学)
- SRM 719 Div 1 250 500
- SRM 500 DIV1 B
- TopCoder SRM 663 Div2 Problem 500 - ABBA (思维)
- SRM 615 DIV1 500
- TC SRM 562 DIV 2
- Topcoder SRM 503 DIV1 500 KingdomXCitiesandVillages
- SRM 586 DIV2 500
- SRM 554 - 500 TheBrickTowerMediumDivOne
- TopCoder SRM 651 Div2 Problem 500 - FoxAndSouvenirTheNext (DP)
- srm 152 div1 500(简单概率计算)
- SRM500 DIV Ⅰ
- Topcoder SRM 543 DIV2 1000 EllysThreeRivers & DIV1 500 EllysRivers
- TopCoder SRM 644 Div2 Problem 500 - LostCharacter (贪心)
- SRM 457 Div2 500
- TopCoder SRM 360 DIV2 500 分题目, 需要排列组合么?需要强力法么?