做题记录整理树状数组3 P3960 [NOIP2017 提高组] 列队(2022/9/29)
P3960 [NOIP2017 提高组] 列队
及其抽象的题目,由于实力不足
几乎相当于照着题解打了一遍
以后回来看得再做一遍
#include<bits/stdc++.h>
#define for1(i,a,b) for(int i = a;i<=b;i++)
#define ll long long
#define mp(a,b) make_pair(a,b)
using namespace std;
const ll inf=600010;
struct node{
ll x;
ll y;
ll id;
bool flag;
}dl[300050];
vector<ll> v[300050];
vector<ll> a;
ll n,m,q,len,len2,st,tj;
ll p[2*300050];
ll t1[2*300050],t2[2*300050];
ll lb(ll x)
{
return x&-x;
}
void xg(ll x,ll y,ll *t)
{
while(x<=inf)
{
t[x]+=y;
x+=lb(x);
}
}
ll cx(ll x,ll *t)
{
ll re = 0;
while(x > 0)
{
re+=t[x];
x-=lb(x);
}
return re;
}
bool cmp1(node x,node y)
{
if(x.x!=y.x)
return x.x<y.x;
return x.id<y.id;
}
bool cmp2(node x,node y)
{
return x.id<y.id;
}
int main()
{
scanf("%lld%lld%lld",&n,&m,&q);
len=n;
for1(i,1,q)
{
scanf("%lld%lld",&dl[i].x,&dl[i].y);
dl[i].id=i;
dl[i].flag=false;
}
for1(i,1,n)
p[i]=i*m*1ll;
for1(i,1,inf)
t1[i]=t2[i]=lb(i);
sort(dl+1,dl+1+q,cmp1);
st=1;tj=1;
while(st <= q)
{
while(tj<q&&dl[st].x==dl[tj+1].x) tj++;
a.clear();len2=m;
for1(i,st,tj)
{
if(dl[i].y==m)
{
dl[i].flag=true;
continue;
}
ll l=1,r=len2;
ll mid;
while(l < r)
{
mid=(l+r)>>1;
if(cx((l+r)/2,t2)>=dl[i].y)
r=mid;
else
l=mid+1;
}
xg(l,-1,t2);
a.push_back(l);
dl[i].y=l;
len2++;
}
for(ll i=0;i<a.size();i++)
xg(a[i],1,t2);
st=tj+1;
}
sort(dl+1,dl+1+q,cmp2);
for1(i,1,q)
{
ll ans;
if(!dl[i].flag)
if(dl[i].y<m)
{
ans=1ll*(dl[i].x-1)*m+dl[i].y;
printf("%lld\n",ans);
}
else
{
dl[i].y=dl[i].y-m;
ans=v[dl[i].x][dl[i].y];
printf("%lld\n",ans);
}
ll l=1,r=len;
ll mid;
while(l<r)
{
mid=(l+r)>>1;
if(cx(mid,t1)>=dl[i].x)
r=mid;
else
l=mid+1;
}
xg(l,-1,t1);
if(!dl[i].flag)
v[dl[i].x].push_back(p[l]);
else
{
ans=p[l];
printf("%lld\n",ans);
}
p[++len]=ans;
}
return 0;
}

浙公网安备 33010602011771号