zoukankan      html  css  js  c++  java
  • 【XSY2892】【GDSOI2018】谁是冠军

    题目来源:noi2018模拟测试赛(二十三)T3 san

    为什么noi模拟赛里会做到省选原题啊……

    题意:

    Description

    有n个人,简单起见把他们编号为1到n,每个人有三项指标分别是攻击力,防御力和血量。现在要进行n-1场比赛,每次在剩下的人里面随机地选出两个人进行比赛,当一个人有大于等于两项指标严格大于另一个人时,这个人获得胜利。每次比赛,胜者留下,败者淘汰。

    现在请你求出所有可能成为冠军(留到最后)的人。

    Input

    第1行有一个整数n,表示人数为n。

    接下来n行,每行有三个整数$a_i,b_i,c_i$分别表示编号为i的人的攻击力,防御力和血量。

    数据保证对于任意两个人的同一项指标值不会相同。

    Output

    按编号从小到大输出有可能成为冠军的人的编号,每行输出一个数。

    Hint

    对于$60\%$的数据$1leq nleq 5000$

    对于$100\%$的数据$1leq nleq 100000$

    题解:

    首先60分很简单,暴力建图,即如果x能胜y就从x到y建有向边,最后从每个点出发看能否遍历整个图就好了;

    也可以tarjan缩点之后直接找入度为0的联通块,块内的点就是答案;

    但这样做依然是$O(n^2)$的,复杂度瓶颈在于边数是$O(n^2)$的,因此很容易想到线段树优化建图;

    由于他的要求是至少两维小于,所以可以两两拆开来做三遍;

    那么先把第一维排序,第二维离散化后开一颗权值线段树,新加入一个点i就将它连向权值在$[1,i的第二维权值-1]$内的区间;

    这样子做一个点最多只会连向$O(logn)$个区间,所以能过;

    注意修改具有时效性,所以要边加边连,具体见代码。

    代码:

      1 #include<algorithm>
      2 #include<iostream>
      3 #include<cstring>
      4 #include<cstdio>
      5 #include<cmath>
      6 #include<queue>
      7 #include<stack>
      8 #define inf 2147483647
      9 #define eps 1e-9
     10 using namespace std;
     11 typedef long long ll;
     12 typedef double db;
     13 struct edge{
     14     int v,next;
     15 }a[20000001];
     16 struct uni{
     17     int a,b,c,id;
     18 }p[100001];
     19 struct node{
     20     int ls,rs,v;
     21 }t[500001];
     22 int n,tot=0,tid=0,bcc=0,tim=0,cnt,rt,dfn[6000001],low[6000001],blg[6000001],head[6000001];
     23 int ans[100001],anss=0;
     24 stack<int>s;
     25 bool cmp(uni a,uni b){
     26     return a.a<b.a;
     27 }
     28 bool _cmp(uni a,uni b){
     29     return a.b<b.b;
     30 }
     31 void add(int u,int v){
     32     //printf("Added %d %d
    ",u,v);
     33     a[++tot].v=v;
     34     a[tot].next=head[u];
     35     head[u]=tot;
     36 }
     37 void build(int &u,int l,int r){
     38     u=++cnt;
     39     t[u].v=0;
     40     if(l==r)return;
     41     int mid=(l+r)/2;
     42     build(t[u].ls,l,mid);
     43     build(t[u].rs,mid+1,r);
     44 }
     45 void updata(int u,int l,int r,int p,int x){
     46     if(l==r){
     47         t[u].v=x;
     48         return;
     49     }
     50     int mid=(l+r)/2;
     51     if(p<=mid)updata(t[u].ls,l,mid,p,x);
     52     else updata(t[u].rs,mid+1,r,p,x);
     53     if(t[t[u].ls].v&&t[t[u].rs].v){
     54         t[u].v=++tid;
     55         add(tid,t[t[u].ls].v);
     56         add(tid,t[t[u].rs].v);
     57     }else t[u].v=t[t[u].ls].v+t[t[u].rs].v;
     58 }
     59 void query(int u,int l,int r,int L,int R,int id){
     60     if(!t[u].v)return;
     61     if(l==L&&r==R){
     62         add(id,t[u].v);
     63         return;
     64     }
     65     int mid=(l+r)/2;
     66     if(L<=mid)query(t[u].ls,l,mid,L,min(mid,R),id);
     67     if(mid<R)query(t[u].rs,mid+1,r,max(mid+1,L),R,id);
     68 }
     69 void link(){
     70     sort(p+1,p+n+1,cmp);
     71     cnt=0;
     72     build(rt,1,n);
     73     //puts("----12----");
     74     for(int i=1;i<=n;i++){
     75         query(rt,1,n,1,p[i].b-1,p[i].id);
     76         updata(rt,1,n,p[i].b,p[i].id);
     77     }
     78     cnt=0;
     79     build(rt,1,n);
     80     //puts("----13----");
     81     for(int i=1;i<=n;i++){
     82         query(rt,1,n,1,p[i].c-1,p[i].id);
     83         updata(rt,1,n,p[i].c,p[i].id);
     84     }
     85     sort(p+1,p+n+1,_cmp);
     86     cnt=0;
     87     build(rt,1,n);
     88     //puts("----23----");
     89     for(int i=1;i<=n;i++){
     90         query(rt,1,n,1,p[i].c-1,p[i].id);
     91         updata(rt,1,n,p[i].c,p[i].id);
     92     }
     93 }
     94 void tarjan(int u){
     95     dfn[u]=low[u]=++tim;
     96     s.push(u);
     97     for(int tmp=head[u];tmp!=-1;tmp=a[tmp].next){
     98         int v=a[tmp].v;
     99         if(!dfn[v]){
    100             tarjan(v);
    101             low[u]=min(low[u],low[v]);
    102         }else if(!blg[v])low[u]=min(low[u],dfn[v]);
    103     }
    104     if(low[u]==dfn[u]){
    105         blg[u]=++bcc;
    106         int nw=s.top();
    107         while(nw!=u){
    108             nw=s.top();
    109             blg[nw]=bcc;
    110             s.pop();
    111         }
    112     }
    113 }
    114 int main(){
    115     memset(head,-1,sizeof(head));
    116     scanf("%d",&n);
    117     for(int i=1;i<=n;i++){
    118         scanf("%d%d%d",&p[i].a,&p[i].b,&p[i].c);
    119         p[i].id=i;
    120     }
    121     tid=n;
    122     link();
    123     for(int i=1;i<=n;i++){
    124         if(!dfn[i]){
    125             tarjan(i);
    126         }
    127     }
    128     for(int i=1;i<=n;i++){
    129         if(blg[i]==bcc)ans[++anss]=i;
    130     }
    131     for(int i=1;i<=anss;i++){
    132         printf("%d
    ",ans[i]);
    133     }
    134     return 0;
    135 }
  • 相关阅读:
    C++笔记--模板
    C++笔记--抽象机制
    C++--VECTOR的简单应用
    C++面试笔记--STL模板与容器
    C++面试笔记--指针和引用
    《转载》什么变量在堆内存里存放,什么变量在栈内存里存放
    C++面试笔记--const、sizeof
    C++面试笔记--宏定义
    C++笔记--指针数组和结构
    C++笔记--异常
  • 原文地址:https://www.cnblogs.com/dcdcbigbig/p/10082087.html
Copyright © 2011-2022 走看看