您的位置:首页 > 其它

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

2017-11-21 14:45 537 查看
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,&a
4000
mp;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,不知道是干嘛的。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  acm
相关文章推荐