zoukankan      html  css  js  c++  java
  • 数据结构(脑洞题,BIT):COGS 2394. 比赛

    比赛

    时间限制:1 s   内存限制:256 MB

    【题目描述】

       n(n≤100000)个人编号为0到n-1,每人都有一个能力值,大小在0到n-1之间,各不相同,他们之间有c场比赛,每场比赛指定一个区间 [l,r],当前第l个到第r个中能力值最大的获胜,其他的都被淘汰,不再出现在候选之列,现在你是n个人中的一个,也要参加这比赛,但你可以选择已经排 好的n-1人之间的n个位置中的一个进行插入,使得自己赢的场数最多,输出最小的位置。

    【输入格式】

       第一行三个数n c k,k是你的能力值。

       接下来n-1行表示前n-1个人的能力值。

       最后c行表示比赛,保证比赛合法。

    【输出格式】

       一行即答案。

    【样例输入】

    5 3 3

    1

    0

    2

    4

    1 3

    0 1

    0 1

    【样例输出】

    1

      这道题,发现对于一个比赛,求出其实际上对应的人分别是哪些,假想每个人自己一个人比赛一次,再考虑对于比赛建树,一个A节点是另一个节点B的子节点仅当A的最强者参加了比赛B,维护胜利者的能力值。假设要参加某场比赛,那么发现这场比赛中最后一个人被挤出去了,所以对于树中节点不统计最后那个人的信息,但在整合子树时考虑。

     1 #include <iostream>
     2 #include <cstring>
     3 #include <cstdio>
     4 using namespace std;
     5 const int maxn=200010;
     6 int bit[maxn],N,fa[maxn];
     7 int a[maxn],Max[maxn];
     8 int ID[maxn],dp[maxn];
     9 int L[maxn],R[maxn];
    10 int n,c,k;
    11 
    12 void Add(int x,int d){
    13     while(x<=N){
    14         bit[x]+=d;
    15         x+=x&(-x);
    16     }
    17 }
    18 
    19 int Pos(int k){
    20     int p=0;
    21     for(int i=N;i;i>>=1)
    22         if(bit[p+(i>>1)]<k)
    23             k-=bit[p+=i>>1];
    24     return p+1;
    25 }
    26 
    27 int main(){
    28     freopen("competition.in","r",stdin);
    29     freopen("competition.out","w",stdout);
    30     scanf("%d%d%d",&n,&c,&k);
    31     for(N=1;N<=n;N<<=1);
    32     for(int i=1;i<n;i++){
    33         scanf("%d",&a[i]);
    34         Add(i,1);ID[i]=i;
    35         L[i]=R[i]=i;
    36     }Add(n+1,1);
    37     for(int i=1,l,r;i<=c;i++){
    38         scanf("%d%d",&l,&r);l++,r++;
    39         L[n+i]=Pos(l);R[n+i]=Pos(r+1)-1;
    40         for(int j=l;j<=r;j++){
    41             int x=ID[Pos(j)];fa[x]=n+i;
    42             Max[n+i]=max(Max[n+i],Max[x]);
    43             if(j!=r)Max[n+i]=max(Max[n+i],a[R[x]]);
    44         }
    45         ID[L[n+i]]=n+i;
    46         for(int j=r;j>l;j--)
    47             Add(Pos(j),-1);
    48     }
    49     
    50     for(int i=c;i>=1;i--)
    51         dp[n+i]=Max[n+i]<k?dp[fa[n+i]]+1:0;
    52     
    53     int M=0,p=1;
    54     for(int i=1;i<=n;i++)
    55         if(dp[fa[i]]>M)
    56             M=dp[fa[i]],p=i;
    57     printf("%d
    ",p-1);        
    58     return 0;
    59 }
  • 相关阅读:
    使用Perl5获取有道词典释义
    Compress a Folder/Directory via Perl5
    为该目录以及子目录添加index.html
    学习Perl6: slice fastq file
    Javascript Regexp match and replace
    赋值运算符函数
    扑克牌顺子
    翻转单词顺序VS左旋转字符串
    和为S的两个数字VS和为S的连续正数序列
    数组中只出现一次的数字
  • 原文地址:https://www.cnblogs.com/TenderRun/p/5688384.html
Copyright © 2011-2022 走看看