当前位置: 首页 > news >正文

*题解:P3960 [NOIP 2017 提高组] 列队

原题链接

解析

考虑 \(x = 1\) 怎么做,可以发现此时只有第 \(1\) 列和第 \(m\) 行会发生变动,将其拼起来可以视作一个数列,操作就是单点删除和结尾插入。怎么维护呢?不一定要平衡树,有一种用树状数组的做法:维护每个位置上的数的存在情况,1 / 0 表示这个位置上 有 / 没有 数。这样,要找第 \(k\) 个元素,就相当于找使得前缀和 \(\ge k\) 的最小下标 \(i\),我们借助另一个数组 \(a\) 存储下标对应的元素,就可以求得元素值;删除操作变为置 \(0\);加入操作变为置 1 的同时在数组中添加对应元素。

对于其余情况,我们需要进一步观察性质。\(n\cdot m\) 很大,我们不可能维护整个方阵,但是 \(q\) 次询问对应着 \(q\) 个元素,我们能否只维护因为询问而变动的元素呢?我们依旧遵循先前转化为 0/1 串的思想,考虑每一行的前 \(m - 1\) 个元素与最后一列(把最后一列单独摘出来方便处理,不然向前看齐后会导致对应不上之前的行)删除位于 \((x,y)\) 的元素就意味着在第 \(x\) 行中,第 \(y\) 个元素对应位置置 \(0\),新增元素 \((x,m)\),对应位置置 \(1\),在第 \(m\) 列中,第 \(x\) 个元素对应位置置 \(0\),新增元素 \((x,y)\),对应位置置 1。

可以发现,最多新增元素数量总和不超过 \(2q\),于是我们可以只维护新增元素。那么非新增元素如何处理?由于对于非新增元素而言,每行相对独立,其余行的操作影响不到这一行,所以可以把询问离线下来一行一行处理。

时间复杂度 \(O(q\log^2n)\)

代码

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int N = 3e5 + 5,M = 500 * 500,mod = 998244353;
struct Q{int x,y,id;	friend bool operator < (Q a,Q b){return a.x != b.x ? a.x < b.x : a.id < b.id;}
}qu[N],q2[N];
int b[N * 3],cnt[N],cntq[N],pre[N];
vector<ll> npos[N];//用于存储下标对应元素
ll res[N];
void add(int x,int k){for(;x < N * 3;x += x & -x){b[x] += k;}
}
int ask(int x){int res = 0;for(;x;x -= x & -x){res += b[x];}return res;
}
int find(int x,int k){//查找第 i 行的第 k 个新增元素,第 n + 1 行是第 m 列int pr = ask(pre[x - 1]);int l = pre[x - 1] + 1,r = pre[x];while(l < r){int mid = l + r >> 1;if(ask(mid) - pr >= k) r = mid;else l = mid + 1;}return l - pre[x - 1];
}
int main(){ios::sync_with_stdio(false);cin.tie(0);
//	freopen("in.txt","r",stdin);
//	freopen("out.txt","w",stdout);int n,m,q;cin>>n>>m>>q;for(int i=1;i<=q;i++){cin>>qu[i].x>>qu[i].y;qu[i].id = i;q2[i] = qu[i];}sort(q2 + 1,q2 + q + 1);for(int i=1;i<=n;i++){cnt[i] = m - 1;//第 i 行中剩余非新增元素个数}	vector<int> v;for(int i=1;i<=m - 1;i++){add(i,1);}for(int i=1;i<=q;i++){int x = q2[i].x,y = q2[i].y,id = q2[i].id;if(y < m) cntq[x]++;//便于在树状数组中分配位置if(q2[i].x != q2[i - 1].x){for(int j : v){add(j,1);}v.clear();}if(y > cnt[x]) continue;	int l = 1,r = m - 1;while(l < r){int mid = l + r >> 1;if(ask(mid) >= y) r = mid;else l = mid + 1;}cnt[x]--;add(l,-1);v.push_back(l);res[id] = 1ll * (x - 1) * m + l;		}memset(b,0,sizeof(b));cntq[n + 1] = n + q;//每次询问必定导致在最后一列尾插,加上初始的 n 个for(int i=1;i<=n + 1;i++){pre[i] = pre[i - 1] + cntq[i];//第 i 行分配到的起始下标为 (pre[i - 1],pre[i]]cnt[i] = m - 1;}	for(int i=1;i<=n;i++){add(pre[n] + i,1);npos[n + 1].push_back(1ll * i * m);}for(int i=1;i<=q;i++){int x = qu[i].x,y = qu[i].y,id = qu[i].id;if(y <= cnt[x]){	cnt[x]--;int t = find(n + 1,x);npos[x].push_back(npos[n + 1][t - 1]);npos[n + 1].push_back(res[id]);add(pre[x - 1] + npos[x].size(),1);add(pre[n] + t,-1);add(pre[n] + n + i,1); }else if(y == m){int t = find(n + 1,x);npos[n + 1].push_back(npos[n + 1][t - 1]);add(pre[n] + t,-1);add(pre[n] + n + i,1);res[id] = npos[n + 1][t - 1];}else{int k = find(x,y - cnt[x]),t = find(n + 1,x);//要找的是第 x 行第 y 个元素,但是 vector 只存了新增的元素,所以要减去非新增元素个数npos[x].push_back(npos[n + 1][t - 1]);npos[n + 1].push_back(npos[x][k - 1]);add(pre[x - 1] + k,-1);add(pre[n] + t,-1);add(pre[x - 1] + npos[x].size(),1);add(pre[n] + n + i,1);res[id] = npos[x][k - 1];}cout<<res[id]<<'\n';}return 0;
}
http://www.jsqmd.com/news/37036/

相关文章:

  • PyTorch - whats the difference between models training mode and evaluation mode?
  • 【CI130x 离在线】C++ 11智能指针 std::unique_ptr
  • Doxygen 入门
  • 第21天(简单题中等题 二分查找、排序)
  • CSAPP学习笔记(施工中)
  • 当Mb连不上虚拟机的时候,这是因为啥?我应该怎么解决?? - fish666
  • 计算不确定度
  • 会议开了一整天,记录却只有三行?
  • Day17盒子模型中设置外边距时的问题
  • 基于Github Action 配置Java Python Go. Rust Nodejs C++ 实现自动发布功能
  • File文件
  • 2025 年 11 月蔬菜配送厂家推荐排行榜,新鲜生鲜水果,有机食堂食材,生鲜蔬菜配送中心,蔬菜配送平台,新鲜蔬菜配送上门公司推荐
  • TensorFlow2 Python深度学习 - TensorFlow2框架入门 - 使用Keras构建逻辑回归
  • 2025 年 11 月食堂承包厂家推荐排行榜:学校、工厂、企业、单位、医院、工地、科技园、工业园、产业园、养老院食堂承包公司精选
  • 2025年保洁公司权威推荐榜单:驻场保洁/钟点保洁/开荒保洁/外包保洁/商场保洁/办公楼保洁/工厂保洁/医院保洁/企业保洁服务优选指南
  • 今天学的是编译型与解释型的运行流程
  • 在线甘特图工具选型指南:5款产品深度对比评测
  • 2025 年 11 月食堂承包厂家推荐排行榜,学校食堂承包,工厂食堂承包,企业单位食堂承包,医院工地科技园食堂承包公司优选
  • 漏洞赏金实战:我是如何轻松获得2500美元奖金的
  • 华为网络设备重启-保存-清楚配置恢复出厂配置命令
  • 2025.11.10总结
  • 2025 年 11 月 PFA 隔膜阀厂家推荐排行榜,PFA 隔膜阀,防腐隔膜阀,高纯隔膜阀,耐酸碱隔膜阀公司推荐
  • 推荐一种异步线程执行过程中更新进度的方法
  • 2025 年 11 月食堂承包厂家推荐排行榜,学校食堂承包,工厂食堂承包,企业单位食堂承包,医院工地科技园食堂承包公司精选
  • 希尔排序快速排序归并排序
  • 2025 年 11 月电源适配器厂家推荐排行榜,12V2A电源适配器,12V电源适配器,24V电源适配器,笔记本电源适配器公司推荐
  • shadcn之表单
  • 2025 年 11 月粘度计厂家推荐排行榜,在线粘度计,旋转粘度计,振动粘度计,实验室旋转粘度计,反应釜在线粘度计公司推荐
  • Numpy - numpy.random.randn()
  • flask: 用Flask-Uploads实现文件上传