PUBG 1V3 线段树扫描线

PUBG 1V3

这个题目我觉得好难写啊。

感觉自己码力不太行啊。

题目大意是,给你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\n", cnt, i);
		h = max(-maxn + 1, y - d) - 1;
		que[cnt++] = edge(l, r, h, -1, i);
		// printf("que[%d] id=%d\n", 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\n", 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\n", que[i].l, que[i].r, que[i].y);
		// printf("i=%d ans[%d]=%d\n\n",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\n", 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\n", end_ans[id]);
	}
	return 0;
}

  

 

posted @ 2019-08-20 17:13  EchoZQN  阅读(145)  评论(0编辑  收藏  举报