AFO

ARC080E

倒着考虑

每次拿出的第一个必须是奇数位置,第二个必须是偶数位置。每次删数都不能跨过已被删去的位置。

事实上只要开个堆维护一下区间就行了。但是众所周知我zz,所以我写的线段树


#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>

using namespace std;

const int M = 1000001;
int n,m,k,a[M],d[2][M],mr[M],tag[M],R[M],w[2][M];

void update(int now)
{
	if(d[0][now*2]>d[0][now*2+1])
	{
		d[0][now]=d[0][now*2+1];
		w[0][now]=w[0][now*2+1];
	}
	else 
	{
		d[0][now]=d[0][now*2];
		w[0][now]=w[0][now*2];
	}
	if(d[1][now*2]>d[1][now*2+1])
	{
		d[1][now]=d[1][now*2+1];
		w[1][now]=w[1][now*2+1];
	}
	else 
	{
		d[1][now]=d[1][now*2];
		w[1][now]=w[1][now*2];
	}
}

void built(int now,int l,int r)
{
	if(l==r)
	{
		int t=l&1;
		d[!t][now]=0x3f3f3f3f;
		d[t][now]=a[l];
		w[t][now]=l;
		mr[now]=n;
		return ;
	}
	int mid=(l+r)>>1,t=0;
	built(now*2,l,mid); built(now*2+1,mid+1,r);
	update(now);
	mr[now]=n;
}

void pd(int now)
{
	if(tag[now]) 
	{
		swap(d[0][now*2],d[1][now*2]);
		swap(d[0][now*2+1],d[1][now*2+1]);
		swap(w[0][now*2],w[1][now*2]);
		swap(w[0][now*2+1],w[1][now*2+1]);
		tag[now*2]^=1; tag[now*2+1]^=1;
		tag[now]=0;
	}
	mr[now*2]=min(mr[now*2],mr[now]);
	mr[now*2+1]=min(mr[now*2+1],mr[now]);
}

int ask1(int now,int l,int r)
{	
	if(l==r) {R[l]=mr[now]; d[1][now]=0x3f3f3f3f; return l;}
	int mid=(l+r)>>1,k; pd(now);
	if(d[1][now]==d[1][now*2]) k=ask1(now*2,l,mid);
	else k=ask1(now*2+1,mid+1,r);
	update(now);
	return k;
}

int ask2(int now,int l,int r,int L,int R)
{
	if(l>=L && r<=R) return w[0][now];
	
	int mid=(l+r)>>1,g,k=0; pd(now);
	if(L<=mid) k=ask2(now*2,l,mid,L,R);
	if(R>mid) 
	{
		g=ask2(now*2+1,mid+1,r,L,R);
		if(a[g]<a[k]) k=g;
	}
	return k;
}

void mody2(int now,int l,int r,int L,int R,int x)
{
	if(l>=L && r<=R)
	{
		if(x)
		{
			tag[now]^=1;
			swap(d[0][now],d[1][now]);
			swap(w[0][now],w[1][now]);
		}
		mr[now]=min(mr[now],R);
		return ;
	}
	int mid=(l+r)>>1; pd(now);
	if(L<=mid) mody2(now*2,l,mid,L,R,x);
	if(R>mid) mody2(now*2+1,mid+1,r,L,R,x);
	update(now);
}

void mody1(int now,int l,int r,int x)
{
	if(l==r)
	{
		d[0][now]=0x3f3f3f3f;
		w[0][now]=0;
		return ;
	}
	int mid=(l+r)>>1; pd(now);
	if(x<=mid) mody1(now*2,l,mid,x);
	else mody1(now*2+1,mid+1,r,x);
	update(now);
}

int main()
{
	scanf("%d",&n); a[0]=0x3f3f3f3f;
	for(int i=1;i<=n;i++) scanf("%d",&a[i]);
	built(1,1,n);
	for(int i=1;i<=n/2;i++)
	{
		int k=ask1(1,1,n);
		printf("%d ",a[k]);
		int g=ask2(1,1,n,k+1,R[k]);
		printf("%d ",a[g]);
		mody1(1,1,n,g);
		if(g-k>1)mody2(1,1,n,k+1,g-1,1);
		if(k!=1)mody2(1,1,n,1,k-1,0);
	}
}
posted @ 2019-10-11 18:56  ZUTTER☮  阅读(148)  评论(0编辑  收藏  举报