Gym - 101572G -(set&细节)|(模拟&理解)|树状数组&好题-Galactic Collegiate Programming Contest

33 篇文章 0 订阅
14 篇文章 0 订阅

http://codeforces.com/gym/101572/attachments
给定一n个人过题的情况。
输入 a,b, 表示第a个人 花了b分钟过了一道题。
至于排名,和acm的一样,过题数优先,一样则花费时间越少越靠前。
问你a的时时排名(如果过题数 和时间都一样则并列)


我开始的思路是发现只有每次更新,只有这个人才可能超过1号。更新ans(ans为超过1的人数)。
所以就记录 每个人过的题数和总时间。模拟。
当1更新时(过一题),只能减少上次和他题数一样大并且罚时比他小的人 和 这次题数一样但是罚时比他大 的人。
当 非1更新时,如果他现在大于1,就加。
或者他现在等于1,但是罚时小, 也加。
这里写图片描述
。。考虑了连续1 增加的情况。(增加的只能算一个)。
但没考虑 连续非1 的增加, ans会计算多次。
(如果是连续两个 不同的非1, 可以计算正确。
但是如果是连续两个 相同的非1 并且第一次更新 执行第二个if,第二次自然可以执行 第一个if。。。。 这个没有想到)
于是加一个vis。 暴力过了

#include <bits/stdc++.h>
using namespace std;
const int maxn=1e5+200;
vector<int>q;
/* erase就算了。很慢。
*/
int tim[maxn];
int num[maxn];
bool vis[maxn];
int main()
{    int m,n,a,b;
      int ans=0;
      vector<int>::iterator it;
     scanf("%d%d",&m,&n);
          for(int i=0;i<n;i++){
              scanf("%d%d",&a,&b);
                num[a]++;
                tim[a]+=b;
                if(num[a]==1)
                     q.push_back(a);
                if(a==1){
                   for(it=q.begin();it!=q.end();it++){
                       int to=*it;
                       if(to==1)continue;
                       if(num[to]+1==num[1]&&(tim[to]<(tim[1]-b))) {ans--;
                       vis[to]=false;
                       //q.erase(it);
                       }
                       else if(num[1]==num[to]&&tim[to]>=tim[1])
                        {ans--;
                        vis[to]=false;
                        //q.erase(it);
                        }
                   }
                }
                else {
                    if(num[a]==num[1]+1&&!vis[a]) {ans++;vis[a]=true;}
                    if(num[a]==num[1]&&tim[a]<tim[1]&&!vis[a]) {ans++;vis[a]=true;}
                }
                printf("%d\n",ans+1);
          }
    return 0;
}

2 用set模拟。这个很好理解。
但硬是错了好几十遍。。
① set重载小于号, 没有重载完全。就是有的变量大小没有判断。
这里写图片描述
(像这样重载,目的是为了 按x升序,若x相等则 y降序。但是实际上只按照了x排序, 造成的一种情况就是 若很多人 x有相同值,则只能存一个。。因为这算相等。)
② 要用三个变量,一个 过题数,一个 时间,那么另一个干嘛呢? 仅仅是花瓶么?? 不是,。。因为可能 不同的人 有相同的过题数和时间,那样就只能存一个。。。我tm。我对set的理解太浅薄了。以为只是一个sort。也是再内部判断他们是否相同的标志啊!!!

#include<bits/stdc++.h>
using namespace std;
/* 这种思路比较明了,代码也很短。属于那种懂思路就可以写出来的题。。
但是完全没想到啊,记得多校时也有一个set的
*/
struct node
{
    int x,y,z;
    friend bool operator < (node a,node b)
    {    /*if(a.x!=b.x)
        return a.x<b.x;
        if (a.y!=b.y) return a.y>b.y;
        return a.z>b.z;
     */
      if(a.x!=b.x)
      return a.x<b.x;
      if(a.y!=b.y)
        return a.y>b.y;
       return a.z>b.z;
    }
    node (int _a,int _b,int _z){
        x=_a;
        y=_b;
        z=_z;
    }
};//重载
set<node> s;
int n,m;
int num[110000],tim[110000];
int main()
{   int a,b;
    /*s.insert(node(1,2,1));
     s.insert(node(2,3,1));
     s.insert(node(2,4,1));
     node to=*s.begin();
     cout<<to.y<<endl;
*/
    scanf("%d%d",&m,&n);
            for(int i=0;i<n;i++){
                scanf("%d%d",&a,&b);
                s.erase(node(num[a],tim[a],a));
                num[a]++;
                tim[a]+=b;
                if(num[a]>num[1]&&a!=1)
                  {s.insert(node(num[a],tim[a],a));
                  //cout<<"!"<<endl;
                 // cout<<"sizshi"<<s.size()<<endl;
                  }
                else if(num[a]==num[1]&&tim[a]<tim[1]&&a!=1){
                    s.insert(node(num[a],tim[a],a));
                }
                while(!s.empty()){
                      node to=*s.begin();
                      //cout<<"cece"<<to.y<<endl;
                      if(to.x>num[1]) break;
                      else if(to.x==num[1]&&to.y<tim[1]) break;
                      s.erase(s.begin());
                      //cout<<to.z<<"????"<<to.y<<endl;
                }
                printf("%d\n",s.size()+1);
            }

    return 0;
}

事后总结:
①即使 set里没有相应元素,erase也是可以的,大不了没删成嘛
②有大佬用 pb库 搞了一搞set,不知道是干嘛的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值