zoukankan      html  css  js  c++  java
  • 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
    ", 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;
    }
    

      

  • 相关阅读:
    this 指向 及 调用方式
    页面布局上 左 右底部
    Thread Safety线程安全
    sql查删更
    LinuxMysql命令操作数据库
    excel链接sharepoint 用于 Excel 的 Microsoft Power Query
    W7无法更新
    发票点数计算
    sharepoint OWA问题解决
    zend studio 做前端推荐安装的插件
  • 原文地址:https://www.cnblogs.com/EchoZQN/p/11384185.html
Copyright © 2011-2022 走看看