样例不过,看一下我的动态开点的思路看能不能做
查看原帖
样例不过,看一下我的动态开点的思路看能不能做
1025259
Kopicy_sama楼主2023/8/21 18:41

借鉴了第K大数的做法,我用sum记录了每个区间的实际存在点的数量,结果查询排位的时候第一个点没问题,后面全部变成零。

#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);
		}
	}
}
2023/8/21 18:41
加载中...