社区讨论
样例不过,看一下我的动态开点的思路看能不能做
P3960[NOIP 2017 提高组] 列队参与者 1已保存回复 1
讨论操作
快速查看讨论及其快照的属性,并进行相关操作。
- 当前回复
- 1 条
- 当前快照
- 1 份
- 快照标识符
- @lo1qxmme
- 此快照首次捕获于
- 2023/10/23 01:32 2 年前
- 此快照最后确认于
- 2023/11/03 02:10 2 年前
借鉴了第K大数的做法,我用sum记录了每个区间的实际存在点的数量,结果查询排位的时候第一个点没问题,后面全部变成零。
CPP#include<bits/stdc++.h>
using namespace std;
#define ll int
#define ri register int
const int N=3e5+5;
ll sum[N<<2],ls[N<<2],rs[N<<2],cnt=1,t[N<<2],pos[N<<2];
ll rt[N];
ll n,m,q;
void insert(ll &p,ll l,ll r,ll x,ll v){
if(!p) p=++cnt;
if(l==r){
t[p]=v;
sum[p]=1;
pos[p]=l;
return;
}
ll mid=l+r>>1;
if(x<=mid) insert(ls[p],l,mid,x,v);
else insert(rs[p],mid+1,r,x,v);
sum[p]=sum[ls[p]]+sum[rs[p]];
}
void insert2(ll &p,ll l,ll r,ll x,ll v){
if(!p) p=++cnt;
if(l==r){
t[p]=v;
sum[p]=0;
pos[p]=l;
return;
}
ll mid=l+r>>1;
if(x<=mid) insert(ls[p],l,mid,x,v);
else insert(rs[p],mid+1,r,x,v);
}
ll query(ll p,ll l,ll r,ll x){
if(l==r){
return p;
}
ll mid=l+r>>1,kkk=sum[ls[p]];
if(kkk>=x) return query(ls[p],l,mid,x);
else if(kkk<x) return query(rs[p],mid+1,r,x-kkk);
}
int main(){
std::ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
cin>>n>>m>>q;
for(ri i=1;i<=n;i++){
for(ri j=1;j<=m-1;j++){
insert(rt[i],1,m+q,j,(i-1)*m+j);
}
}
for(ri i=1;i<=n;i++){
insert(rt[n+1],1,n+q,i,i*m);
}
ll x,y;
ll nn=n,mm=m;
for(ri i=1;i<=q;i++){
nn++;
mm++;
cin>>x>>y;
if(y==m){
ll pp=query(rt[n+1],1,n+q,x);//询问并第x大数
cout<<t[pp]<<endl;
insert(rt[n+1],1,n+q,nn,t[pp]);
insert2(rt[n+1],1,n+q,pos[pp],0);
}
else{
ll pp1=query(rt[x],1,m+q,y);
cout<<t[pp1]<<endl;
ll pp2=query(rt[n+1],1,n+q,x);
insert(rt[n+1],1,n+q,nn,t[pp1]);
insert2(rt[n+1],1,n+q,pos[pp2],0);
insert(rt[x],1,m+q,mm,t[pp2]);
insert2(rt[x],1,m+q,pos[pp1],0);
}
}
}
回复
共 1 条回复,欢迎继续交流。
正在加载回复...