ZOJ - 4068 Airdrop (思维)(The 2018 ACM-ICPC Asia Qingdao Regional Contest - K)

Airdrop


Time Limit: 2 Seconds      Memory Limit: 65536 KB


PUBG is a multiplayer online battle royale video game. In the game, up to one hundred players parachute onto an island and scavenge for weapons and equipment to kill others while avoiding getting killed themselves. Airdrop in this game is a key element, as airdrops often carry with them strong weapons or numerous supplies, helping players to survive.


Airdrop in the game(?)

Consider the battle field of the game to be a two-dimensional plane. An airdrop has just landed at point  (both  and  are integers), and all the  players on the battle field, where  (both  and are integers) indicates the initial position of the -th player, start moving towards the airdrop with the following pattern:

  • If the position of a living player at the beginning of this time unit is not equal to , he will begin his next move.
    • Let's say he is currently at point . For his next move, he will consider four points , ,  and .
    • He will select one of the four points whose Manhattan distance to the airdrop  is the smallest to be the destination of his next move. Recall that the Manhattan distance between two points  and  is defined as .
    • If two or more points whose Manhattan distance to the airdrop is the same, he will use the following priority rule to break the tie:  has the highest priority to be selected,  has the second highest priority,  has the third highest priority, and  has the lowest priority.
    • At the end of this time unit, he arrives at his destination.
  • If the position of a living player at the beginning of this time unit is equal to , he will continue to fatten his backpack with the supplies in the airdrop and stays at .

But the battle is tough and it's almost impossible for all the players to arrive at the airdrop safely. If two or more players meet at point  other than , where both  and  are integers, they will fight and kill each other and none of them survive.

BaoBao is a big fan of the game and is interested in the number of players successfully arriving at the position of the airdrop, but he doesn't know the value of . Given the value of  and the initial position of each player, please help BaoBao calculate the minimum and maximum possible number of players successfully arriving at the position of the airdrop for all , where  is the set of all integers (note that  can be positive, zero or negative).

Input

There are multiple test cases. The first line of the input contains an integer , indicating the number of test cases. For each test case:

The first line contains two integers  and  (, ), indicating the number of players and the  value of the airdrop.

For the following  lines, the -th line contains two integers  and  (), indicating the initial position of the -th player.

It's guaranteed that the sum of  in all test cases will not exceed , and in each test case no two players share the same initial position.

Output

For each test case output one line containing two integers  and  separated by one space.  indicates the minimum possible number of players successfully arriving at the position of the airdrop, while  indicates the maximum possible number.

Sample Input

3
3 2
1 2
2 1
3 5
3 3
2 1
2 5
4 3
2 3
1 3
4 3

Sample Output

1 3
0 3
2 2

Hint

We now explain the first sample test case.

To obtain the answer of , one should consider . The following table shows the position of each player at the end of each time unit when .

Time Player 1 Player 2 Player 3
0 (1, 2) (2, 1) (3, 5)
1 (2, 2) (2, 2) (3, 4)
2 eliminated eliminated (3, 3)
3 eliminated eliminated (3, 2)

To obtain the answer of , one should consider . The following table shows the position of each player at the end of each time unit when .

Time Player 1 Player 2 Player 3
0 (1, 2) (2, 1) (3, 5)
1 (2, 2) (2, 2) (3, 4)
2 (2, 2) (2, 2) (3, 3)
3 (2, 2) (2, 2) (3, 2)
4 (2, 2) (2, 2) (2, 2)

 

解题思路:因为是固定Y坐标,所以我们可以枚举X坐标,X坐标最多也就1e5而已。然后对于每个X坐标,我们暴力的计算所有玩家到那个坐标的距离,然后判断即可。但是这么做复杂度是N^2的,所以我们要高效的计算。我们枚举X坐标时,计算他左边能有多少个幸存者,和右边有多少个幸存者即可,我们可以先从左向右枚举,然后可以实现快速转移的计算X坐标左边有多少个生存者,然后从右往左枚举,计算右边有多少个幸存者,结合答案即可。

 

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MAXN=200010;
int N,X,Y;
int x[MAXN];
int y[MAXN];

int num[MAXN*2];
int tot=0;
vector<int> G[MAXN];

int ans[MAXN];
int vis[MAXN];
vector<int> used;

int main()
{
    int T;
    scanf("%d",&T);
    while(T--){
        scanf("%d%d",&N,&Y);
        tot=0;
        memset(vis,0,sizeof(vis));
        memset(ans,0,sizeof(ans));

        num[tot++]=0;
        for(int i=1;i<=N;i++){
            scanf("%d%d",&x[i],&y[i]);
            G[x[i]].clear();
            G[x[i]+1].clear();
            num[tot++]=x[i];
            num[tot++]=x[i]+1;
        }

        for(int i=1;i<=N;i++)
            G[x[i]].push_back(y[i]);


        sort(num,num+tot);
        tot = unique(num,num+tot)-num;


        int ansmin=0x3f3f3f3f;
        int ansmax=0;

        int pre=0;
        int cnt=0;
        for(int i=0;i<tot;i++){
            X=num[i];
            used.clear();
            ans[X]+=G[X].size();

            for(int j=0;j<G[pre].size();j++){
                int dis=abs(1e5+1-pre)+abs(Y-G[pre][j]);
                vis[dis]++;
                if(vis[dis]==1)
                    cnt++;
                else
                    used.push_back(dis);
            }
            for(int j=0;j<used.size();j++)
            {
                if(vis[used[j]])cnt--;
                vis[used[j]]=0;
            }
            ans[X]+=cnt;
            pre=num[i];
        }

        memset(vis,0,sizeof(vis));
        pre=cnt=0;
        for(int i=tot-1;i>=0;i--){
            X=num[i];
            used.clear();
            for(int j=0;j<G[pre].size();j++){
                int dis=abs(-pre)+abs(Y-G[pre][j]);
                vis[dis]++;
                if(vis[dis]==1)
                    cnt++;
                else
                    used.push_back(dis);
            }
            for(int j=0;j<used.size();j++)
            {
                if(vis[used[j]])cnt--;
                vis[used[j]]=0;
            }
            ans[X]+=cnt;
            ansmin=min(ans[X],ansmin);
            ansmax=max(ans[X],ansmax);
            pre=num[i];
        }
        printf("%d %d\n",ansmin,ansmax);
    }

    return 0;
}

 

 

发布了402 篇原创文章 · 获赞 67 · 访问量 16万+
展开阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 点我我会动 设计师: 上身试试

分享到微信朋友圈

×

扫一扫,手机浏览