我们有n面围墙,这些围墙高度无限!从一架飞机向下看,就像一条条线段一般!我们做些实验,有m只小鸟,它们会不断的飞直到碰撞围墙!确保每一只小鸟放下来,它一定会撞到围墙,而且它会朝着最快撞到围墙的方向去飞,题目保证每只小鸟的四个方向里,只有一个方向是最近的
然后题目最后需要我们输出,每一面墙被小鸟撞过的次数
题目中的墙都是与坐标轴垂直的,一定为竖直方向,或水平方向。
n最大可以达到50000,m最大也可以达到50000,限定时间6秒钟!
题目不会一开始就把小鸟放在墙上
思考这样的一个问题,我们可以对墙分开考虑,这里我假设 x1<=x2 ,y1 <= y2
情况1、对于水平方向的墙,x1 != x2,y1 == y2,那么根据小鸟的位置 x y,当x1<= x <=x2时,这面墙是一定可以够得到的!然后到这面墙的距离就是 |y1 - y|
情况2、对于竖直方向的墙,x1 == x2,y1 != y2,那么根据愤怒的小鸟的位置,当 y1 <= y <= y2时,这面墙也一定够的到吧!距离是 |x1 - x|
然后水平和墙和竖直的墙都考虑到了,那么还可能存在这面墙就与 小鸟在同一行或者同一列的情况。
情况3、与小鸟在用一列的墙 x1 == x2 == x,然后 y2 < y 或者 y1 > y,这种的话,对于 y2 < y的,y - y2就是它的距离,对于 y1 > y 的,y1 - y 就是它的距离。
情况4、与小鸟在同一行的墙,y1 == y2 == x,然后 x2 < x 或者 x1 > x,这种的话,对于x2 < x的墙,x - x2是它的距离,对于x1 > x的墙,x1 - x是它的距离。
然后有i可能存在一只小鸟撞多个墙的情况,但是我觉得最多只撞的到2面墙,从题目大意上看,墙的高度无限,是不会有重合的,唯一的重合就是竖直与水平相交!而小鸟撞多个墙的情况,就是它撞到了这个交点,所以撞到2面墙,见下图!
针对情况1,我们把x1 != x2的墙都记录下来,根据x1排序放到row数组,然后按2048的大小进行分桶,每个桶内按 x2排序,然后针对每个桶的数组,建立一颗线段树(归并树)树上的每个节点按照 y1 排序,针对每次 x y,首先二分 row数组,找到 x1<=x的区间,确定涉及到的桶,在桶内二分找到 x2 >= x的区间,然后去线段树上查出这些区间里最接近 y 的 y1,并用abs(y - y1)更新结果。对于桶外的元素(不超过2048)那就去row数组一个个判断了,如果 x2>=x那么用abs(y - y1)更新结果即可。
针对情况2,我们把y1 != y2的墙都记录下来,根据y1排序放在col数组,然后按2048的大小进行分桶,每个桶内按 y2排序。针对每个桶的数组,建立一颗线段树(归并树)树上每个节点按照y1排序,针对每次x y,首先二分col数组,找到y1<=y的区间,确定涉及到的桶,在桶内二分找到y2>=y的区间,然后去线段树上查出这些区间里最接近x的x1,并用abs(x - x1)更新结果。对于桶外的元素(不超过2048)那就去col数组一个个判断了,如果y2>=y那就用abs(x - x1)更新结果即可。
针对情况3,我们可以把x1 == x2的墙,放在数组里,然后优先根据 x1 排序,对x1相同的,根据 y1 排序,这样我们根据小鸟的位置 x y ,只需要把它传进去数组二分得到idx,然后判断idx的位置 x1是不是与 x相等,是的话,距离是 y1 - y(lower_bound得到的是第一个不小于的到idx,则idx要么x1==x且y1>=y,要么x1>x),判断下这个距离是不是最近的,然后idx--,再判断idx的位置是不是x1与x相等,是的话,用 y - y2更新结果
针对情况4,我们可以把y1 == y2的墙,放在数组里,优先根据 y1 排序,对于 y1 相同的,根据 x1 排序,然后也是把 x 和 y传进来,去二分得到idx,判断 idx位置的y1==y?,若相等,则 判断距离 x1 - x更新结果,再判断idx-1位置的y1==y?,若相等,用 x - x2更新结果。
需要注意的一点是,我在使用vector建树的时候超时了,最好不用vector,用指针。
- #include
- #include
- using namespace std;
- struct Same
- {
- int _same, _other, _idx;
- Same(int _same = 0, int _other = 0, int _idx = 0) : _same(_same), _other(_other), _idx(_idx) {}
- };
- bool compareSame(const Same &a, const Same &b)
- {
- return a._same != b._same ? a._same < b._same : a._other < b._other;
- }
- Same sameX[50009], sameY[50009];
- int sameXSize, sameYSize;
- const int B = 2048;
- typedef pair<int, int> P;
- int rowSize, colSize;
- P row[50009], col[50009], bktR[27][2057], bktC[27][2057];
- // P datR[27][100][100], datC[27][100][100];
- P **datR[27], **datC[27];
- int x[50009], y[50009], x1[50009], x2[50009], y1[50009], y2[50009], n, m;
- void swapIfNeed(int i)
- {
- int tmp;
- if (x1[i] > x2[i])
- {
- tmp = x1[i];
- x1[i] = x2[i];
- x2[i] = tmp;
- }
- if (y1[i] > y2[i])
- {
- tmp = y1[i];
- y1[i] = y2[i];
- y2[i] = tmp;
- }
- }
- void input()
- {
- rowSize = 0, colSize = 0, sameXSize = 0, sameYSize = 0;
- scanf("%d%d", &n, &m);
- for (int i = 0; i < n; i++)
- {
- scanf("%d%d%d%d", &x1[i], &y1[i], &x2[i], &y2[i]);
- swapIfNeed(i);
- if (x1[i] != x2[i])
- {
- row[rowSize].first = x1[i];
- row[rowSize].second = i;
- rowSize++;
- }
- if (y1[i] != y2[i])
- {
- col[colSize].first = y1[i];
- col[colSize].second = i;
- colSize++;
- }
- if (x1[i] == x2[i])
- {
- sameX[sameXSize]._same = x1[i];
- sameX[sameXSize]._other = y1[i];
- sameX[sameXSize]._idx = i;
- sameXSize++;
- }
- if (y1[i] == y2[i])
- {
- sameY[sameYSize]._same = y1[i];
- sameY[sameYSize]._other = x1[i];
- sameY[sameYSize]._idx = i;
- sameYSize++;
- }
- }
- for (int i = 0; i < m; i++)
- {
- scanf("%d%d", &x[i], &y[i]);
- }
- }
- void sortAll()
- {
- sort(row, row + rowSize);
- sort(col, col + colSize);
- sort(sameX, sameX + sameXSize, compareSame);
- sort(sameY, sameY + sameYSize, compareSame);
- }
- void build(int idx, int i, int l, int r, bool isR)
- {
- if (r - l == 1)
- {
- if (isR)
- {
- datR[idx][i] = new P[1];
- datR[idx][i][0].first = y1[bktR[idx][l].second];
- datR[idx][i][0].second = bktR[idx][l].second;
- }
- else
- {
- datC[idx][i] = new P[1];
- datC[idx][i][0].first = x1[bktC[idx][l].second];
- datC[idx][i][0].second = bktC[idx][l].second;
- }
- }
- else
- {
- int lch = i * 2 + 1;
- int rch = i * 2 + 2;
- int mid = (l + r) / 2;
- build(idx, lch, l, mid, isR);
- build(idx, rch, mid, r, isR);
- if (isR)
- {
- datR[idx][i] = new P[r - l];
- merge(datR[idx][lch], datR[idx][lch] + (mid - l), datR[idx][rch], datR[idx][rch] + (r - mid), datR[idx][i]);
- }
- else
- {
- datC[idx][i] = new P[r - l];
- merge(datC[idx][lch], datC[idx][lch] + (mid - l), datC[idx][rch], datC[idx][rch] + (r - mid), datC[idx][i]);
- }
- }
- }
- int calcSize(int _size)
- {
- int size = 1;
- while (size < _size)
- {
- size = size * 2;
- }
- return size * 2 - 1;
- }
- void buckedMethod()
- {
- for (int i = 0; i < rowSize; i++)
- {
- bktR[i / B][i - ((i / B) * B)].first = x2[row[i].second];
- bktR[i / B][i - ((i / B) * B)].second = row[i].second;
- }
- for (int i = 0; i < rowSize; i = i + B)
- {
- int bucketR = i + B;
- bucketR = (bucketR > rowSize ? rowSize : bucketR);
- sort(bktR[i / B], bktR[i / B] + (bucketR - i));
- int size = calcSize(bucketR - i);
- datR[i / B] = new P *[size];
- build(i / B, 0, 0, (bucketR - i), true);
- }
- for (int i = 0; i < colSize; i++)
- {
- bktC[i / B][i - ((i / B) * B)].first = y2[col[i].second];
- bktC[i / B][i - ((i / B) * B)].second = col[i].second;
- }
- for (int i = 0; i < colSize; i = i + B)
- {
- int bucketR = i + B;
- bucketR = (bucketR > colSize ? colSize : bucketR);
- sort(bktC[i / B], bktC[i / B] + (bucketR - i));
- int size = calcSize(bucketR - i);
- datC[i / B] = new P *[size];
- build(i / B, 0, 0, (bucketR - i), false);
- }
- }
- int ansIdx[50009][10], ans[50009], ansLen[50009], ansDist[50009], _current;
- void updateAns(int dist, int idx)
- {
- if (ansDist[_current] == 0 || ansDist[_current] == dist)
- {
- ansIdx[_current][ansLen[_current]] = idx;
- ansLen[_current] = ansLen[_current] + 1;
- ansDist[_current] = dist;
- }
- if (ansDist[_current] > dist)
- {
- ansLen[_current] = 0;
- ansIdx[_current][ansLen[_current]] = idx;
- ansLen[_current] = ansLen[_current] + 1;
- ansDist[_current] = dist;
- }
- }
- void handleSame(Same current, int size, bool isR)
- {
- if (size <= 0)
- {
- return;
- }
- int idx;
- if (isR)
- {
- idx = lower_bound(sameX, sameX + size, current, compareSame) - sameX;
- }
- else
- {
- idx = lower_bound(sameY, sameY + size, current, compareSame) - sameY;
- }
- if (isR)
- {
- if (idx < size && sameX[idx]._same == current._same)
- {
- updateAns(sameX[idx]._other - current._other, sameX[idx]._idx);
- }
- idx--;
- if (idx >= 0 && sameX[idx]._same == current._same)
- {
- updateAns(current._other - y2[sameX[idx]._idx], sameX[idx]._idx);
- }
- }
- else
- {
- if (idx < size && sameY[idx]._same == current._same)
- {
- updateAns(sameY[idx]._other - current._other, sameY[idx]._idx);
- }
- idx--;
- if (idx >= 0 && sameY[idx]._same == current._same)
- {
- updateAns(current._other - x2[sameY[idx]._idx], sameY[idx]._idx);
- }
- }
- }
- void handleTreeNode(P current, int bkt, int tree, int size, bool isR)
- {
- int idx;
- if (isR)
- {
- idx = lower_bound(datR[bkt][tree], datR[bkt][tree] + size, current) - datR[bkt][tree];
- }
- else
- {
- idx = lower_bound(datC[bkt][tree], datC[bkt][tree] + size, current) - datC[bkt][tree];
- }
- for (int i = idx - 1; i <= idx; i++)
- {
- if (i >= 0 && i < size)
- {
- if (isR)
- {
- updateAns(abs(datR[bkt][tree][i].first - current.first), datR[bkt][tree][i].second);
- }
- else
- {
- updateAns(abs(datC[bkt][tree][i].first - current.first), datC[bkt][tree][i].second);
- }
- }
- }
- }
- void queryTree(P current, int bkt, int _l, int _r, int i, int l, int r, bool isR)
- {
- if (_l >= r || _r <= l)
- {
- }
- else if (l >= _l && r <= _r)
- {
- handleTreeNode(current, bkt, i, r - l, isR);
- }
- else
- {
- queryTree(current, bkt, _l, _r, i * 2 + 1, l, (l + r) / 2, isR);
- queryTree(current, bkt, _l, _r, i * 2 + 2, (l + r) / 2, r, isR);
- }
- }
- void handleBucket(int size, int first, int second, bool isR)
- {
- if (size <= 0)
- {
- return;
- }
- int limit;
- if (isR)
- {
- limit = upper_bound(row, row + size, P(first, 0x3f3f3f3f)) - row;
- }
- else
- {
- limit = upper_bound(col, col + size, P(first, 0x3f3f3f3f)) - col;
- }
- if (limit <= 0)
- {
- return;
- }
- for (int i = 0; i < size; i = i + B)
- {
- int bucketL = i;
- int bucketR = i + B;
- bucketR = (bucketR > size ? size : bucketR);
- if (bucketL >= limit)
- {
- break;
- }
- if (bucketR <= limit)
- {
- int idx;
- if (isR)
- {
- idx = lower_bound(bktR[i / B], bktR[i / B] + (bucketR - bucketL), P(first, -0x3f3f3f3f)) - bktR[i / B];
- }
- else
- {
- idx = lower_bound(bktC[i / B], bktC[i / B] + (bucketR - bucketL), P(first, -0x3f3f3f3f)) - bktC[i / B];
- }
- if (idx < (bucketR - bucketL))
- {
- queryTree(P(second, -0x3f3f3f3f), i / B, idx, (bucketR - bucketL), 0, 0, (bucketR - bucketL), isR);
- }
- continue;
- }
- for (int j = bucketL; j < limit; j++)
- {
- int need;
- if (isR)
- {
- need = x2[row[j].second];
- }
- else
- {
- need = y2[col[j].second];
- }
- if (need >= first)
- {
- if (isR)
- {
- updateAns(abs(y1[row[j].second] - second), row[j].second);
- }
- else
- {
- updateAns(abs(x1[col[j].second] - second), col[j].second);
- }
- }
- }
- }
- }
- void solve()
- {
- for (int i = 0; i < m; i++)
- {
- _current = i;
- handleBucket(rowSize, x[i], y[i], true);
- handleSame(Same(x[i], y[i], -0x3f3f3f3f), sameXSize, true);
- handleBucket(colSize, y[i], x[i], false);
- handleSame(Same(y[i], x[i], -0x3f3f3f3f), sameYSize, false);
- }
- }
- void putAns()
- {
- for (int i = 0; i < m; i++)
- {
- for (int j = 0; j < ansLen[i]; j++)
- {
- ans[ansIdx[i][j]] = ans[ansIdx[i][j]] + 1;
- }
- }
- for (int i = 0; i < n; i++)
- {
- printf("%d\n", ans[i]);
- }
- }
- int main()
- {
- input();
- sortAll();
- buckedMethod();
- solve();
- putAns();
- return 0;
- }
题目限时6000ms,差不多用了4600ms过了。