BZOJ 4415: [Shoi2013]发牌

线段树模拟

#include
using namespace std;
int sz[20000005];
void update(int t){
	sz[t]=sz[t<<1]+sz[t<<1|1];
}
void build(int t,int l,int r){
	if (l==r){
		sz[t]=1;
		return;
	}
	int mid=(l+r)>>1;
	build(t<<1,l,mid);
	build(t<<1|1,mid+1,r);
	update(t);
}
void modify(int t,int l,int r,int x){
	if (l==r){
		sz[t]=0;
		return;
	}
	int mid=(l+r)>>1;
	if (x<=mid) modify(t<<1,l,mid,x);
	else modify(t<<1|1,mid+1,r,x);
	update(t);
}
int query_suf(int t,int l,int r,int x){
	if (l==r) return 0;
	int mid=(l+r)>>1;
	if (x<=mid) return sz[t<<1|1]+query_suf(t<<1,l,mid,x);
	else return query_suf(t<<1|1,mid+1,r,x);
}
int query_pre(int t,int l,int r,int x){
	if (l==r) return sz[t];
	int mid=(l+r)>>1;
	if (x<=mid) return query_pre(t<<1,l,mid,x);
	else return sz[t<<1]+query_pre(t<<1|1,mid+1,r,x);
}
int query_Kth(int t,int l,int r,int K){
	if (l==r) return l;
	int mid=(l+r)>>1;
	if (K<=sz[t<<1]) return query_Kth(t<<1,l,mid,K);
	else return query_Kth(t<<1|1,mid+1,r,K-sz[t<<1]);
}
int main(){
	int n;
	scanf("%d",&n);
	int last=0,m=n;
	build(1,0,n-1);
	for (int i=1; i<=n; i++){
		int x;
		scanf("%d",&x);
		x%=m;
		m--;
		int ID=query_suf(1,0,n-1,last);
		if (ID>=x){
			int now=query_pre(1,0,n-1,last);
			now+=x;
			last=query_Kth(1,0,n-1,now);
		}
		else{
			x-=ID;
			last=query_Kth(1,0,n-1,x);
		}
		int now=query_pre(1,0,n-1,last);
		modify(1,0,n-1,last);
		printf("%d\n",last+1);
		if (now>m) now=1;
		last=query_Kth(1,0,n-1,now);
	}
	return 0;
}

  

转载于:https://www.cnblogs.com/silenty/p/9858369.html

你可能感兴趣的:(BZOJ 4415: [Shoi2013]发牌)