JXJJOI2018_T2_tank

题目描述

Lemon最近迷上了一款坦克对战游戏。在这款游戏中,Lemon需要驾驶一辆坦克与敌军对战。

坦克有很多不同的武器,每种武器有各自的特点,而Lemon所要做的就是合适地发射这些武器,对敌军造成最大的伤害。具体来说,每个武器都有两个参数:攻击力D和攻击半径R。为了简化题意,我们保证所有武器的攻击力D均不相同,所有武器的攻击半径R也均不相同。

Lemon决定对这些武器的性能进行评价。当然,评价不能只看攻击力D,也不能只看攻击半径R。Lemon觉得一件武器A优于另一件武器B,当且仅当A的攻击力大于B的攻击力且A的攻击半径大于B的攻击半径。

接下来,Lemon想要对武器进行分组,Lemon按照以下方式分组:
首先,我们定义f(A,S)为真当且仅当在武器集合S中的任何武器都不比武器A性能更优秀。
(1)令i=0;
(2)令i=i+1;令S=还没被分组的武器集合;
(3)对于每一件S中的武器A,如果f(A,S)为真,则将武器A标记为第i组(注意S在这个过程中始终保持不变);
(4)如果所有武器均被分组则结束,否则转2。
给定N个武器的D和R,你的任务是按照Lemon的规则对这些武器进行分组。

输入输出格式

输入格式

输入文件第一行包含一个正整数N,表示武器的个数。

接下来N行,每行两个正整数D、R,描述一件武器的攻击力和攻击半径。保证所有的D两两不同,所有的R两两不同。

输出格式

输出文件包含N行,每行一个正整数,第i行的数表示第i件武器被分在了哪一组。

样例

INPUT

5
1 4
2 2
3 3
4 1
5 5

OUTPUT

2
3
2
2
1

HINT

首先我们发现武器5比武器1性能更优,所以武器1不在第1组。同理武器2、3、4也不在第1组。
但没有武器比武器5性能更优,因此武器5在第1组。
接下来还剩武器1、2、3、4没被分组。我们发现这些武器中没有武器比武器1更优,于是武器1在第2组,同理武器3、4也在第2组。
接下来只剩武器2了,武器2在第3组。
此时所有武器均被分组,过程结束。

对于20%的数据,N≤100;对于40%的数据,N≤3000;对于100%的数据,N≤100000;1≤R、D≤10^9。

SOLUTION

贪心

\(O(n^2)\)的做法好像不会,因为觉得写的很麻烦,索性放弃。其实写对贪心有一部分就是歪打正着qwq

把每个武器的两个参数\(d,r\),分别为第一关键字和第二关键字排序,得到了以d为主关键字降序的新序列。我们已知,对于第\(i,j\)个武器只有当①\(d_i>d_j\)且②\(r_i>r_j\)时编号为\(i\)的武器才能完全压制编号为\(j\)的武器,这时就不能把\(i,j\)分为一组。

所以当我们把所有武器以\(d\)为主关键字降序排序时已经保证了①条件的成立,所以若要使后面的武器\(i\)能够不被第\(j\)组完全压制,只有满足\(r_i>R_{j}\)时才能成立,若不能成立,我们就开一个新的组,这时候可以看出我们最后的\(R\)数组是满足单调性的,于是就可以二分。

于是我们的\(O(nlogn)\)的算法就出来了。

\(P.S.\)下面是我考场上的代码,其中\(lft\)数组是赘余的,而且变量命名也很奇怪,将就着看吧qwq。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
using namespace std;
#define Min(a,b) ((a<b)?a:b)
#define Max(a,b) ((a>b)?a:b)
inline int read(){
    int x=0,f=1;char ch=getchar();
    while (ch<'0'||ch>'9') {if (ch=='-') f=-1;ch=getchar();}
    while (ch>='0'&&ch<='9') {x=x*10+ch-48;ch=getchar();}
    return x*f;}
const int N=101000;
int n,blg[N],lft[N],rgt[N],L,R,sch;
struct NODE{int d,r,u;}nd[N];
bool cmp(NODE x,NODE y){if (x.d==y.d) return x.r>y.r;return x.d>y.d;}
inline void bsh(int l,int r){
    if (l==r) {sch=l;return;}
    if (l+1==r) {if ((L>=lft[l])||(R>=rgt[l])) sch=l;else sch=r;return;}
    int mid=(l+r)>>1;
    if ((L>=lft[mid])||(R>=rgt[mid])) bsh(l,mid);else bsh(mid+1,r);}
int main(){
    freopen("tank.in","r",stdin);
    freopen("tank.out","w",stdout);
    int i,j;
    n=read();for (i=1;i<=n;++i) {nd[i].d=read();nd[i].r=read();nd[i].u=i;}
    sort(nd+1,nd+1+n,cmp);memset(blg,0,sizeof(blg));
    memset(lft,0,sizeof(lft));memset(rgt,0,sizeof(rgt));
    int cnt=0;
    for (i=1;i<=n;++i){
        L=nd[i].d,R=nd[i].r;
        //printf("*%d *%d:",L,R);
        bsh(1,cnt+1);if (sch==(cnt+1)) cnt++;
        lft[sch]=Max(lft[sch],L);rgt[sch]=Max(rgt[sch],R);
        blg[nd[i].u]=sch;
        //printf("cnt:%d sch:%d\n",cnt,sch);
    }
    for (i=1;i<=n;++i) printf("%d\n",blg[i]);
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/hkpls/p/9826477.html