[NOIP2017 提高组] 列队 题解

编程入门 行业动态 更新时间:2024-10-19 23:38:30

[NOIP2017 提高组] 列队 <a href=https://www.elefans.com/category/jswz/34/1769599.html style=题解"/>

[NOIP2017 提高组] 列队 题解

数据结构。

n = 1 n=1 n=1 的 case:考虑有 m + q m+q m+q 个位置,出队的人直接添加到队尾。维护位置对应的人,每次查询第 k k k 个人的位置。

实现考虑维护 01 序列,表示位置上是 / 否有人,每次查前缀和为 k k k 的位置即可。

一般情况:每次操作只会影响某一行以及最后一列。考虑将最后一列单独处理。

对于查询 ( x , y ) (x,y) (x,y):需查询第 x x x 行第 y y y 个人的位置以及最后一列第 x x x 个人的位置,维护一下对应编号, y = m y = m y=m 时只用查最后一列。

实现考虑离线树状树组或动态开点线段树,线段树 / 树状树组上二分可以做到 log ⁡ \log log,总时间复杂度 O ( n log ⁡ n ) O(n \log n) O(nlogn)。

树状树组实现显然要离线,仅用一个 BIT 预处理每次非最后一列操作在对应行的位置。

#include<bits/stdc++.h>
#define int long long
using namespace std;const int N = 3e5 + 5; 
const int V = 6e5;int n, m, q, tree[N<<1], x[N], y[N], num[N];int lowbit(int x) {return x&(-x);}
void add(int x, int d){for(;x <= V; x += lowbit(x)) tree[x] += d;}
int select(int k)
{int pos = 0, sum = 0;for(int i=20; i>=0; i--){pos += (1 << i);if(pos > V or sum + tree[pos] >= k) pos -= (1 << i);else sum += tree[pos];}return pos + 1;
}signed main()
{ios::sync_with_stdio(0); cin.tie(0);cin >> n >> m >> q;for(int i=1; i<=V; i++) tree[i] = lowbit(i);vector <vector<int>> cmd(n+1);for(int i=1; i<=q; i++){cin >> x[i] >> y[i];if(y[i] != m) cmd[x[i]].push_back(i);}for(int i=1; i<=n; i++){for(auto id : cmd[i])num[id] = select(y[id]), add(num[id], -1);for(auto id : cmd[i]) add(num[id], 1);}vector <vector<int>> row(n+1);vector <int> column;for(int i=1; i<=q; i++){int in, out, p = select(x[i]); add(p, -1);if(y[i] != m){out = (num[i] < m) ? ((x[i]-1)*m+num[i]) : row[x[i]][num[i]-m], in = (p <= n) ? (p*m) : column[p-n-1];row[x[i]].push_back(in), column.push_back(out);}else{out = (p <= n) ? (p*m) : column[p-n-1];column.push_back(out);}cout << out << "\n";	}
}

更多推荐

[NOIP2017 提高组] 列队 题解

本文发布于:2023-11-17 02:57:33,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1637456.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:题解

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!