社区讨论

样例不过,看一下我的动态开点的思路看能不能做

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 条回复,欢迎继续交流。

正在加载回复...