Gym

来源:互联网 发布:淘宝首页装修设计尺寸 编辑:程序博客网 时间:2024/06/07 00:41

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,不知道是干嘛的。

原创粉丝点击