题意
给定一个 n*m
的队列,每次操作选取一个位置 (i,j)
出队,然后填补空位。输出每次出队的编号。
Solution:
考点:模拟+数据结构。
算法一
对于 n,m<=1000
的数据,直接暴力模拟;
对于 n=1
的数据,可以树状数组维护:

稍加修改,可以得到 x=1
的做法,

期望得分 60pts
。
算法二
再来看 n=2
的情况:

于是不难得到下述算法:
- 建立一个以第
m
行为元素的序列 - 对于每次操作,判断是否在当前行内,如果是则先在当前行内删除,再插入列尾;否则在列中查询排名
x
的数,先将它删去,然后插入列尾。如果是第一种情况就要把列中排名 x
的数插到行中去。
比较棘手的是空间会爆。观察到被删除的节点只有 q
个,所以可以 动态开点+线段树二分
,只有一个 log
。
可以用 线段树
实现。时间复杂度 O(nlogn)
。
纯属口胡,不喜勿喷。
#include<bits/stdc++.h>
#define INF 1e9
#define ll long long
#define PII pair<ll,int>
#define All(a) a.begin(),a.end()
#define L t[p].lson
#define R t[p].rson
using namespace std;
const int mx=4e7+5;
inline int read() {
int x=0,f=1; char c=getchar();
while(c<'0'||c>'9') {if(c=='-') f=-1; c=getchar();}
while(c>='0'&&c<='9') {x=(x<<1)+(x<<3)+c-'0'; c=getchar();}
return x*f;
}
int n,m,q,cnt[mx],tot;
ll res;
struct SegmentTree{
int lson,rson,siz,add;
ll val;
}t[mx];
void PushUp(int p) {
t[p].siz=t[L].siz+t[R].siz;
}
void update(int p,int l,int r,int x,ll y) {
if(l==r) {
t[p].val=y; t[p].siz=1;
return;
}
int mid=l+r>>1;
if(!t[p].lson) t[p].lson=++tot;
if(!t[p].rson) t[p].rson=++tot;
if(t[p].add) {
t[p].add=0;
t[L].siz=mid-l+1; t[L].add=1;
t[R].siz=r-mid; t[R].add=1;
}
if(x<=mid) {
update(L,l,mid,x,y);
}
else {
update(R,mid+1,r,x,y);
}
PushUp(p);
}
int query(int p,int l,int r,int x) {
if(l==r) {
return l;
}
int mid=l+r>>1;
if(!t[p].lson) t[p].lson=++tot;
if(!t[p].rson) t[p].rson=++tot;
if(t[p].add) {
t[p].add=0;
t[L].siz=mid-l+1; t[L].add=1;
t[R].siz=r-mid; t[R].add=1;
}
if(x<=t[L].siz) return query(L,l,mid,x);
return query(R,mid+1,r,x-t[L].siz);
}
void Delete(int p,int l,int r,int x) {
if(l==r) {
t[p].siz=0; res=t[p].val;
return;
}
int mid=l+r>>1;
if(!t[p].lson) t[p].lson=++tot;
if(!t[p].rson) t[p].rson=++tot;
if(t[p].add) {
t[p].add=0;
t[L].siz=mid-l+1; t[L].add=1;
t[R].siz=r-mid; t[R].add=1;
}
if(x<=mid) Delete(L,l,mid,x);
else Delete(R,mid+1,r,x);
PushUp(p);
}
void build(int p,int l,int r,int ql,int qr) {
if(ql<=l&&r<=qr) {
t[p].siz=r-l+1; t[p].add=1;
return;
}
if(!t[p].lson) t[p].lson=++tot;
if(!t[p].rson) t[p].rson=++tot;
int mid=l+r>>1;
if(ql<=mid) build(L,l,mid,ql,qr);
if(mid<qr) build(R,mid+1,r,ql,qr);
PushUp(p);
}
int main() {
n=read(),m=read(),q=read(); tot=n+1;
for(int i=1;i<=n;i++) {
build(i,1,m+q,1,m-1);
cnt[i]=m-1;
}
for(int i=1;i<=n;i++) {
update(n+1,1,n+q,i,1ll*i*m);
}
for(int i=1;i<=q;i++) {
int x=read(),y=read();
if(y<=m-1) {
int z=query(x,1,m+q,y);
Delete(x,1,m+q,z); ll tmp;
if(z<=m) tmp=1ll*(x-1)*m+z;
else tmp=res;
printf("%lld\n",tmp);
z=query(n+1,1,n+q,x);
Delete(n+1,1,n+q,z);
update(x,1,m+q,m+i-1,res);
update(n+1,1,n+q,n+i,tmp);
}
else {
int z=query(n+1,1,n+q,x);
Delete(n+1,1,n+q,z);
printf("%lld\n",res);
update(n+1,1,n+q,n+i,res);
}
}
}
__EOF__
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· DeepSeek 开源周回顾「GitHub 热点速览」