标签:用户访问 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