这个题目我觉得好难写啊。
感觉自己码力不太行啊。
题目大意是,给你n个人,n个人组成m个队伍,每个队伍最多4个人。
然后给你每一个人的位置队伍信息还有攻击范围。
问当一个队伍剩下一个人的时候他最多可以杀多少个人。
这个题目是有扫描线的思想。
首先我们用一个结构体来存更新点的信息,然后用一个结构体来存查询边的信息。
然后像扫描线一样的对点和边进行排序。
然后更新点的信息,如果到了要查询边的信息就查询。
最后统计答案。
这个大体思路还是比较简单,但是这个细节的处理很麻烦。
因为对于每一个人如果是他的队友肯定是不可以杀的,所以要删去这些点,这个就用前向星类似的方式去存它队友所存放的
数组的编号,但是这样就说明不可以直接对结构体排序,所以这个时候有一个小小的技巧就是用一个数组来排序,结构体本身不打乱顺序。
还有就是如何判断到查询边的信息的时候呢?就是如果更新下一个点的时候的y都大于这个查询边的信息,那就查询。
然后就是要注意范围,因为x,y的范围是1e6的绝对值,如果超出这个范围的查询的边都是0。
#include <cstdio> #include <cstring> #include <algorithm> #include <cstdlib> #include <cstring> #include <queue> #include <vector> using namespace std; const int maxn = 1e6 + 10; struct node { int x, y, team, nxt, d; node(int x=0,int y=0,int team=0,int nxt=0,int d=0):x(x),y(y),team(team),nxt(nxt),d(d){} }ex[maxn]; struct edge { int l, r, y, f, id; edge(int l=0,int r=0,int y=0,int f=0,int id=0):l(l),r(r),y(y),f(f),id(id){} }que[maxn*4]; int p[maxn]; int head[maxn]; bool cmp1(edge a,edge b) { return a.y < b.y; } bool cmp2(int a,int b) { return ex[a].y < ex[b].y; } int ans[maxn], end_ans[maxn]; int num[maxn * 10]; void update(int id,int l,int r,int pos) { if(l==r) { num[id] += 1; return; } int mid = (l + r) >> 1; if (pos <= mid) update(id << 1, l, mid, pos); else update(id << 1 | 1, mid + 1, r, pos); num[id] = num[id << 1] + num[id << 1 | 1]; } int query(int id,int l,int r,int x,int y) { if (x <= l && y >= r) return num[id]; int mid = (l + r) >> 1; int ans = 0; if (x <= mid) ans += query(id << 1, l, mid, x, y); if (y > mid) ans += query(id << 1 | 1, mid + 1, r, x, y); return ans; } int main() { int n, m, cnt = 0; scanf("%d%d", &n, &m); memset(head, -1, sizeof(head)); memset(num, 0, sizeof(num)); for (int i = 1; i <= n; i++) { p[i] = i; int x, y, d, team; scanf("%d%d%d%d", &x, &y, &d, &team); ex[i] = node(x, y, team, head[team], d); head[team] = i; int l = max(-maxn + 1, x - d); int r = min(maxn - 1, x + d); int h = min(maxn - 1, y + d); que[cnt++] = edge(l, r, h, 1, i); // printf("que[%d] id=%d ", cnt, i); h = max(-maxn + 1, y - d) - 1; que[cnt++] = edge(l, r, h, -1, i); // printf("que[%d] id=%d ", cnt, i); } sort(que, que + cnt, cmp1); sort(p + 1, p + 1 + n, cmp2); int tot = 1; for (int i = 0; i < cnt; i++) { while (tot <= n && ex[p[tot]].y <= que[i].y) { // printf("tot=%d x=%d ", tot, ex[p[tot]].x); update(1, 1, maxn * 2, ex[p[tot]].x + maxn); tot++; } ans[que[i].id] += que[i].f*query(1, 1, maxn * 2, que[i].l + maxn, que[i].r + maxn); // printf("l=%d r=%d h=%d ", que[i].l, que[i].r, que[i].y); // printf("i=%d ans[%d]=%d ",i, que[i].id, ans[que[i].id]); } for (int i = 1; i <= n; i++) { int team = ex[i].team; int x = ex[i].x, y = ex[i].y, d = ex[i].d; for (int j = head[team]; j != -1; j = ex[j].nxt) { // printf("id=%d j=%d ", id, j); int x1 = ex[j].x, y1 = ex[j].y; if (abs(x1 - x) <= d && abs(y1 - y) <= d) ans[i]--; } end_ans[team] = max(end_ans[team], ans[i]); } int q; scanf("%d", &q); while(q--) { int id; scanf("%d", &id); printf("%d ", end_ans[id]); } return 0; }