列队题解以及注意事项
一道十分interesting的题目
这道题显然要使用数据结构维护。但是n的规模十分大。我们便可以开n棵线段树,动态开点。但是最后一列比较特殊,所以我们再开一棵线段树维护最后一列。至于怎么操作?我们考虑权值线段树。权值线段树一般是维护:权值为[L,r]的数有多少是满足某种条件的。本道题目中我们维护区间[L,R]中有多少个数没有操作过。线段树的长度要开为 max(n,m)+q,这样如果我们查询一个数的位置发现她超过了m,说明她已经不在原位置了,出去的数我们用vector存储,每次直接访问下标就可以查询了。这里的原理就是查询该行排名为k的点。发现这个点之后就将其压入维护最后一列的vector中,并将此时在最后一列中排名为K的点压入改行,就行了。注意特判询问的纵坐标为m的情况
code:
#include<iostream>
#include<cstdio>
#include<queue>
#include<algorithm>
#include<cmath>
#include<set>
#include<cstring>
#include<vector>
#define max MAX
#define maxn 5000006
#define mod 1000000007
#define rep(i,a,b) for (int i=a;i<=b;++i)
#define erep(i,a) for (int i=head[a];i!=-1;i=e[i].next)
#define half (l+r)>>1
#define lson t[s].lc
#define pb push_back
#define all (zmd)
#define rson t[s].rc
using namespace std;
#define int long long
struct zmd
{
int fx,fy;
};
struct hzw
{
int lc,rc,sum;
}t[maxn];
int n,m,mx,tot,q;
inline int MAX(int a,int b) {return a>b?a:b;}
inline void update(int &s,int l,int r,int p)
{
if (!s) s=++tot;
if (l==r)
{
t[s].sum++;
return;
}
int mid=half;
if (p<=mid) update(lson,l,mid,p);
else update(rson,mid+1,r,p);
t[s].sum=t[lson].sum+t[rson].sum;
}
int root[maxn];
inline int query(int s,int l,int r,int p)
{
if (l==r) return l;
int mid = half;
int tmp=(mid-l+1) - t[lson].sum;
if (p<=tmp) return query(lson,l,mid,p);
else return query(rson,mid+1,r,p-tmp);
}
vector<zmd>v[300006];
inline int solve1(int x,int y)
{
int now = query(root[x],1,mx,y),ans;
update(root[x],1,mx,now); // take away
if (now<m)
{
ans=m*(x-1)+now;
v[n+1].pb(all{x,now}); //insert back
}
else
{
zmd wow = v[x][now-m];
ans=m*(wow.fx-1)+wow.fy;
v[n+1].pb(wow);
}
int bk = query(root[n+1],1,mx,x);
update(root[n+1],1,mx,bk);
if (bk<=n) v[x].pb(all{bk,m}); //no used is insert easily
else {zmd wow = v[n+1][bk-n-1];v[x].pb(wow);} //find and insert now
return ans;
}
inline int solve2(int x,int y) // final insert
{
int now=query(root[n+1],1,mx,x);
update(root[n+1],1,mx,now);
zmd wow;
if (now<=n) wow.fx=now,wow.fy=m;
else wow = v[n+1][now-n-1];
v[n+1].pb(wow);
return m*(wow.fx-1)+wow.fy;
}
#undef int
int main()
{
#define int long long
cin>>n>>m>>q;
mx = max(n,m)+q;
rep(i,1,q)
{
int a,b;
scanf("%lld%lld",&a,&b);
printf("%lld\n",b==m?solve2(a,b):solve1(a,b));
}
return 0;
}
注意事项:
define max(a,b) a>b?a:b 有时候会出玄学错误:例子:
看,十分玄妙,所以不要乱define了