LOJ P3960 列队 树状数组 vector

时间:2022-09-18 02:53:33

https://www.luogu.org/problemnew/show/P3960

树状数组预处理之后直接搞就可以了,也不是很好解释,反正就是一个模拟过程的暴力用树状数组维护,还挺巧妙的。

我为什么考场上想不出来嘤嘤嘤

 #include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<vector>
using namespace std;
const int maxn=;
int n,m,q;
int xx[maxn]={},yy[maxn]={};
int num[maxn]={},z[maxn]={};
int lag[maxn]={};
int t[maxn]={},mx;
vector<int>id[maxn];
vector<int>val[maxn];
vector<long long >shu[maxn];
void add(int x,int v){
while(x<=mx){
t[x]+=v;
x+=(x&-x);
}
}
int getit(int x){
int tsn=;
while(x){
tsn+=t[x];
x-=(x&-x);
}return tsn;
}
int Find(int x){
int l=,r=mx,mid;
while(l<r){
mid=(l+r)/;
if(getit(mid)<x)l=mid+;
else r=mid;
}
return l;
}
int main(){
scanf("%d%d%d",&n,&m,&q);
mx=max(n,m)+q;
for(int i=;i<=q;i++){
scanf("%d%d",&xx[i],&yy[i]);
if(yy[i]!=m){
val[xx[i]].push_back(yy[i]);
id[xx[i]].push_back(i);
}
else
z[i]=;
}
for(int i=;i<=mx;i++)add(i,);
for(int i=;i<=n;i++){
int siz=id[i].size();
for(int j=;j<siz;j++){
num[id[i][j]]=Find(val[i][j]);
add(num[id[i][j]],-);
}
for(int j=;j<siz;j++)add(num[id[i][j]],);
}
long long ans;
for(int i=;i<=n;i++)shu[].push_back((long long)i*m);
lag[]=m;
for(int i=;i<=q;i++){
if(z[i]){
ans=shu[][Find(xx[i])];
add(Find(xx[i]),-);
}
else if(num[i]<=m+lag[xx[i]]-){
ans=num[i]<m?(long long)(xx[i]-)*m+num[i]:shu[xx[i]][num[i]-m];
shu[xx[i]].push_back(shu[][Find(xx[i])]);
lag[xx[i]]++;
add(Find(xx[i]),-);
}
else{
ans=shu[][Find(num[i]-m-lag[xx[i]]+xx[i])];
add(Find(num[i]-m-lag[xx[i]]+xx[i]),-);
}
shu[].push_back(ans);lag[]++;
printf("%lld\n",ans);
}
return ;
}