标签:用户访问 nbsp 删除 大小 getc 操作 online 记录 快速
第一行为整数n, k。(1 <= n <= 5 * 10^6,1 <= k <= 1000) n代表有多少次操作,k代表窗口大小。 接下来的n行,每行代表一次操作。每行第一个整数为操作数。 操作数1:用户访问 输入格式: <1, id> 用户ID为[0, INT_MAX]闭区间内的整数。代表拥有此ID的用户对网站进行了一次访问,窗口进行相应移动。 操作数2:询问众数 输入格式:<2> 输出窗口内的众数,如果有多个,输出ID最小的那个。 p.s. 对于询问众数的操作,窗口保证不空 p.s.s. 对于询问众数的操作,窗口可能不满
对于询问众数的操作,每行输出一个整数。
10 5 1 2 1 1 1 2 1 1 1 2 1 1 2 1 3 1 3 2
1 1
题目大意:
起初看到这道题,没读懂是什么意思,一直在纳闷窗口是啥。后来才明白,是实现查询,查询时的前k个访问次数中,访问最多的用户的编号。
分析:
首先,考虑到的是只考虑查询前的前k次访问,复杂度是k*查询次数,如果大部分都是查询明显过不去。
之后,用优先队列去实现,优先队列内容是一个结构体,储存了用户的ID,和访问次数。但是,优先队列不支持删除操作,
所以怎么去实现删除已经超过k个用户的数据呢?我的方法是使用map记录每个用户的访问次数,删除k个之前的用户时,只在map里将其更新。然后,查询时
去循环取优先队列顶部元素,检查这个元素储存的访问次数是否与map里记录的次数相同,如果不相同则该节点作废,出队,再取队列顶部元素,直到相同为止,
然后,交上去,就超时了,将map改成hash_map,优化了输入之后再交,700ms通过。
其实,优先队列写法挂了之后,并没又马上用hash_map,就将程序改为了用set去实现,set的最大值就是set中最后一个元素,插入删除复杂度,log(n),2000ms,超时。。。。。。然后又将map改成hash_map,优化了输入输出之后再交,
700ms通过。。。。。。
ps:hash_map用VC++去交就可以成功编译
//优先队列实现
#include<iostream>
using namespace std;
#include<queue>
#include<cstdio>
#include<hash_map>
typedef long long LL;
inline LL getint()//快速读入
{
LL w = 0, q = 0;
char c = getchar();
while ((c<‘0‘ || c>‘9‘) && c != ‘-‘) c = getchar();
if (c == ‘-‘) q = 1, c = getchar();
while (c >= ‘0‘&&c <= ‘9‘) w = w * 10 + c - ‘0‘, c = getchar();
return q ? -w : w;
}
queue<LL> team;
struct data//优先队列里信息用的结构体
{
LL sj;
LL bh;
bool operator<(const data &b)const
{
if (this->sj == b.sj) return this->bh>b.bh;
return this->sj<b.sj;
}
};
priority_queue<data> preteam;
hash_map<LL, LL> maps;
int n, k;
int main()
{
int rq = 0;
cin >> n >> k;
LL pre;
int ml;
LL dx;
data mx;
for (int i = 1; i <= n; i++)
{
//scanf("%d", &ml);
ml = getint();
if (ml == 1)
{
//scanf("%lld", &dx);
dx = getint();
data np;
maps[dx]++;
np.bh = dx; np.sj = maps[dx];
preteam.push(np);
team.push(dx);
if (team.size() == k + 1)
{
pre = team.front();
maps[pre]--;
team.pop();
}
}
if (ml == 2)
{
mx = preteam.top();
/*循环取优先队列有效值*/
while (mx.sj != maps[mx.bh] && !preteam.empty()) {
preteam.pop();
mx = preteam.top();
}
printf("%d\n", mx.bh);
}
}
return 0;
}
//set实现
#include<iostream>
using namespace std;
#include<queue>
#include<cstdio>
#include<hash_map>
#include<map>
#include<set>
typedef long long LL;
queue<LL> team;
inline LL getint()
{
LL w = 0, q = 0;
char c = getchar();
while ((c<‘0‘ || c>‘9‘) && c != ‘-‘) c = getchar();
if (c == ‘-‘) q = 1, c = getchar();
while (c >= ‘0‘&&c <= ‘9‘) w = w * 10 + c - ‘0‘, c = getchar();
return q ? -w : w;
}
struct data
{
LL sj;
LL bh;
bool operator<(const data &b)const
{
if (this->sj == b.sj) return this->bh>b.bh;
return this->sj<b.sj;
}
};
set<struct data> preset;
hash_map<LL, LL> maps;
int n, k;
int main()
{
set<struct data>::iterator pt;
int rq = 0;
//cin>>n>>k;
n = getint();
k = getint();
LL pre;
int ml;
LL dx;
struct data mx;
for (int i = 1; i <= n; i++)
{
//scanf("%d",&ml);
ml = getint();
if (ml == 1)
{
dx = getint();
// scanf("%lld",&dx);
struct data np;
np.bh = dx; np.sj = maps[dx];
preset.erase(np);
maps[dx]++;
np.sj = maps[dx];
preset.insert(np);
team.push(dx);
if (team.size() == k + 1)
{
pre = team.front();
np.bh = pre; np.sj = maps[pre];
preset.erase(np);
team.pop();
maps[pre]--;
if (maps[pre] == 0) continue;
np.sj = maps[pre];
preset.insert(np);
}
}
if (ml == 2)
{
pt = preset.end();
--pt;//迭代器自减至set最后一个元素的位置
int bh = (*pt).bh;
// cout<<bh<<endl;
printf("%d\n", bh);
}
}
return 0;
}
标签:用户访问 nbsp 删除 大小 getc 操作 online 记录 快速
原文地址:http://www.cnblogs.com/xfww/p/7270292.html