zoukankan      html  css  js  c++  java
  • hdu-5596 GTW likes gt(模拟+优先队列)

    题目链接:

    GTW likes gt

     Time Limit: 2000/1000 MS (Java/Others)
     Memory Limit: 131072/131072 K (Java/Others)
    问题描述

    从前,有nn只萌萌的GT,他们分成了两组在一起玩游戏。他们会排列成一排,第ii只GT会随机得到一个能力值b_ibi​​。在第ii秒的时候,第ii只GT可以消灭掉所有排在他前面的和他不是同一组的且能力值小于他的GT。 为了使游戏更加有趣,GT的首领GTW会发功mm次,第ii次发功的时间为c_ici​​,则在第c_ici​​秒结束后,b_1,b_2,...,b_{c_i}b1​​,b2​​,...,bci​​​​都会增加1。 现在,GTW想知道在第nn秒之后,会有几只GT存活下来。

    输入描述
     
    第一行只有一个整数T(Tleq 5)T(T5),表示测试数据组数。
    第二行有两个整数n,mn,m。表示GT的个数和GTW发功的次数。(1leq n leq 50000,1leq mleq 500001n50000,1m50000)
    第三到n+2n+2行,每行有两个整数a_i,b_iai​​,bi​​,表示第ii只GT在哪个组和他的能力值 (0leq a[i]leq 1,1leq b[i]leq 10^6)(0a[i]1,1b[i]106​​)
    第n+3n+3行到第n+m+2n+m+2行,每行有一个整数c_ici​​,表示GTW第ii次发功的时间。1leq c[i]leq n1c[i]n
    
    输出描述
     
    总共TT行,第ii行表示第ii组数据中,GT存活的个数。
    输入样例
    1
    4 3
    0 3
    1 2
    0 3
    1 1
    1
    3
    4
    输出样例
    3

    题意:

    不说了;

    思路:

    这是一个模拟题;可以用队列的出队模拟被消灭,开两个队列表示不同的组别,然而一般的队列的复杂度跟数组的没区别,所以得用优先队列来降低复杂度;
    那么问题的难点就变成了怎么定义优先级了;
    我们从第一个gt一直到第n个gt,依次入队,在入队的同时要保证不同组别即另一个队列里的比他小的都出队;
    所以我们要按能力的值大小定义优先级,但是能力的大小在变化,这可难办了;
    我们发现,在i秒发功,那么从1到n都将加1,我们可以把b[i]-前i秒的发功次数定义成优先级就可以在判断是否出队的时候队列里的排列是单调的了;
    具体的看代码解释;


    AC代码:

    /*    5596    234MS    2764K    1585 B    G++    LittlePointer*/
    #include <bits/stdc++.h>
    using namespace std;
    const int N=5e4+5;
    typedef long long ll;
    const ll mod=1e9+7;
    int t,n,m,x,flag[N],dp[N];
    struct node
    {
        friend bool operator<(node x,node y)
        {
            return x.fnum>y.fnum;
        }
        int ki,num,pos,fnum;
    };
    node po[N];
    priority_queue<node>qu1,qu2;
    int main()
    {
       scanf("%d",&t);
       while(t--)
       {
           while(!qu1.empty())qu1.pop();
           while(!qu2.empty())qu2.pop();
           scanf("%d%d",&n,&m);
           for(int i=1;i<=n;i++)
           {
               scanf("%d%d",&po[i].ki,&po[i].num);
               po[i].pos=i;
           }
           memset(flag,0,sizeof(flag));
           for(int i=0;i<m;i++)
           {
               scanf("%d",&x);
               flag[x]++;
           }
           dp[0]=0;
           for(int i=1;i<=n;i++)
           {
               dp[i]=dp[i-1]+flag[i];//dp[i]表示前i秒的发功次数;
               po[i].fnum=po[i].num-dp[i-1];
           }
           int cnt=0;
           for(int i=1;i<=n;i++)
           {
              if(po[i].ki==0)
              {
                  qu1.push(po[i]);
                  while(!qu2.empty())
                  {
                      node fr=qu2.top();
                      if(fr.fnum+dp[i]<po[i].num+flag[i])qu2.pop();//dp[i]是不变的fr.fnum+dp[i]=fr.num+dp[i]-dp[fr.pos-1];
                      else break;//单纯的比较fr.num+dp[i]与po[i].num+flag[i]是不对的;
                  }
              }
              else
              {
                  qu2.push(po[i]);
                  while(!qu1.empty())
                  {
                      node fr=qu1.top();
                      if(fr.fnum+dp[i]<po[i].num+flag[i])qu1.pop();
                      else break;
                  }
              }
           }
           printf("%d
    ",qu1.size()+qu2.size());
       }
        return 0;
    }


  • 相关阅读:
    C++ 日期 & 时间
    C++ 引用
    C++ 指针
    C++ 字符串
    C++ 数组
    C++ 数字
    C++ 函数
    C++ 判断
    C++ 循环
    C++ 运算符
  • 原文地址:https://www.cnblogs.com/zhangchengc919/p/5410036.html
Copyright © 2011-2022 走看看