ZSOI2013 花瓶 分塊

題意同上

分塊大法好!

然而之前老師讓我們做比賽的時候時寫了300多行代碼還沒寫對的我一臉懵逼= =

對於分塊的不熟悉卻又不想寫線段樹的我實際上是做大死= =

然後前天晚上真的只交了暴力上去

事後看了下別人的代碼,發現郭隆寫的分塊比較優美,然後仿照他的代碼又寫了一次這道題

loc,BEGIN,END三個宏使我能直接開一個大數組了

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<algorithm>
#define LL long long
#define fo(i,a,b) for(int i = a;i <= b; i++)
#define dfo(i,a,b) for(int i = a ;i >= b;i--)
using namespace std;
inline LL read()
{
	LL d=0,f=1;char s=getchar();
	while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
	while(s>='0'&&s<='9'){d=d*10+s-'0';s=getchar();}
	return d*f;
}
#define N 50005
#define inf 10000000
#define M 300

#define loc(x) (1+(x)/sb)
#define BEGIN(x) (((x)-1)*sb)
#define END(x) (((x)*sb-1)<n?((x)*sb-1):n-1)

bool po[N];
int sz[M],full[M],non[M],cur[M];
int n,m,sb,lb;

void pushlazy(int x)
{
	if(non[x])
	{
		fo(i,BEGIN(x),END(x))po[i]=0;
		non[x]=0;
	}
	if(full[x])
	{
		fo(i,BEGIN(x),END(x))po[i]=1;
		full[x]=0;
	}
}

void buildblocks()
{
	for(sb=0;sb*sb<n;sb++);
	lb=loc(n-1);
	fo(i,1,lb)
	{
		sz[i]=END(i)-BEGIN(i)+1;
		cur[i]=sz[i];
		non[i]=full[i]=0;
	}
}

void F(int beg,int f)
{
	int fb=loc(beg),lv=0,zui=0;
	bool flag1=0,flag2=0,flag=0;
	int fp=-1,lp=-1;
	
	//set the first block
	pushlazy(fb);
	fo(i,beg,END(fb))
	if(!po[i])
	{
		po[i]=1;
		cur[fb]--;
		lp=i;
		flag=1;
		if(fp<0)
		{
			fp=i;
			flag1=1;
		}
		if(--f==0)break;
	}
	if(f==0)
	{
		printf("%d %d\n",fp,lp);
		return ;
	}
	//visit the blocks after
	lv=fb;
	fo(i,fb+1,lb)
	if(cur[i])
	{
		if(fp<0)fp=i;
		flag2=1;flag=1;
		lp=i,lv=i;
		if(f<=cur[i])
		{
			cur[i]-=f;
			zui=f;
			break;
		}else
		{
			f-=cur[i];
			zui=cur[i];
			cur[i]=0;
			full[i]=1;
		}
	}
	if(!flag)
	{
		puts("Can not put any one.");
		return ;
	}
	//if can't finish the first block we can visit in the first
	//then seeking in the first block we visit
	if(!flag1)
	{
		if(non[fp])fp=BEGIN(fp);
		else
		{
			fo(i,BEGIN(fp),END(fp))
			if(!po[i])
			{
				fp=i;
				break;
			}
		}
	}
	//seeking in the last visit block
	if(flag2)
	{
		//push the lazy label-non
		if(non[lp])
		{
			fo(i,BEGIN(lp),END(lp))po[i]=0;
			non[lp]=0;
		}
		//renew it
		fo(i,BEGIN(lp),END(lp))
		if(!po[i])
		{
			po[i]=1;
			if(--zui==0)
			{
				lp=i;
				break;
			}
		}
		
		//renew the label-non
		fo(i,fb+1,lv)non[i]=0;
	}
	printf("%d %d\n",fp,lp);
}
	
void R(int l,int r)
{
	int fb=loc(l),lb=loc(r),ret=0;
	pushlazy(fb);
	if(fb==lb)
	{
		fo(i,l,r)
		if(po[i])
		{
			po[i]=0;
			ret++;
			cur[fb]++;
		}
	}else
	{
		fo(i,l,END(fb))
		if(po[i])
		{
			po[i]=0;
			ret++;
			cur[fb]++;
		}
		pushlazy(lb);
		fo(i,BEGIN(lb),r)
		if(po[i])
		{
			po[i]=0;
			ret++;
			cur[lb]++;
		}
		fo(i,fb+1,lb-1)
		{
			ret+=sz[i]-cur[i];
			non[i]=1;
			full[i]=0;
			cur[i]=sz[i];
		}
	}
	printf("%d\n",ret);
}

int main()
{
	freopen("vase.in","r",stdin);
	freopen("vase.out","w",stdout);
	n=read(),m=read();
	buildblocks();
	fo(i,1,m)
	{
		int ccf=read();
		if(ccf==1)
		{
			int a=read(),f=read();
			F(a,f);
		}else
		{
			int l=read(),r=read();
			R(l,r);
		}
	}
	return 0;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章