2019牛客暑期多校训练营(第十场)

比赛 AC:  B,D,E,H

我过B,E.

补题情况:

---队友过的 且未补题

Ο 自己过的或赛后补题

题号 A B C D E F G H I J K L
状态 . Ο . --- Ο Ο . --- . . . .

 

B:斐波那契数列

观察题目,只让求前1e12,发现56项后每项都大于1e12,结果肯定时56或57项的前1e12中的字符。

然后利用斐波那契数列递推过程,递推出这10个字符分别是什么即可

//KX
#include 
using namespace std;
typedef long long ll;
typedef double db;
const int M= 1e5+7;
ll a[M];
string s[10];
int main()
{
	a[1]=6;
	a[2]=7;
	for(int i=3;i<=57;i++)
	{
		a[i]=a[i-2]+a[i-1];
	//	cout<>t;
	ll n,k;
	while(t--)
	{
		scanf("%lld%lld",&n,&k);
		if(n>=58)
		{
			if(n%2==1)n=57;
			else n=56;
		}
	/*	if(k+9>a[n])
		{
			puts("N");
			continue;
		}*/
		for(ll i=k;i<=k+9;i++)
		{
			if(i>a[n])
			continue;
			ll now=i,nn=n;
			while(1)
			{
			//	printf("%d --- %d \n",nn,now);
				if(nn<=2)
				{
					printf("%c",s[nn][now]);
					break;
				}
				if(now<=a[nn-2])
				{
					nn=nn-2;
				}
				else
				{
					now-=a[nn-2];
					nn=nn-1;

				}
			}
		}
		puts("");
	}
   	return 0;
}


E:分形:

求出n个点的id,排序输出即可

id的求法:

第n级的x,y可以对应到  第n-1级的一个坐标上,

分左上,右上,左下,右下四种情况

其中左下,右下时直接对应的,加上中间的id。

左上,右上比较麻烦,

左上是先对应,再顺时针旋转90度,再取轴对称(因为为了让id的顺序一样)

右上一样,先对应,再逆时针旋转90度,再取轴对称。

递归下去就行了

复杂度n*k

//KX
#include 
using namespace std;
typedef long long ll;
typedef double db;
const int M= 1e6+7;
struct node
{
	ll x, y,id;
}P[M];
void dfs(ll x,ll y,ll now,ll id,int o)
{
//	printf("%lld %lld %lld %lld %d\n",x,y,now,id,o);
	if(now==2)
	{
	/*	P[o].id=id;
		return ;*/
		ll ji=4;
		if(x==1&&y==1)//左上 
		ji=1;
		else if(x==2&&y==1)//左下 
		ji=2;
		else if(x==2&&y==2)//右下
		ji=3;
		else if(x==1&&y==2) //右上 
		ji=4;
		else
		{
		//	printf("%d  %d \n",x,y);
			puts("wa222222222222");
		}
		P[o].id=id+ji;
		return ;
	}
	ll m =now/2;
	ll mm =m/2;
	if(x<=m&&y<=m)//左上 
	{
	//	(m-x),-(m-y) 对应新的坐标 
	// y ,-x	顺时针 
	//-(m-y), -(m-x)//对应旋转和的新的坐标系
	// 2*m-y,  x;
		ll xx=y; 
		ll yy=m+1-x;
		yy=m+1-yy;
		dfs(xx,yy,m,id,o);
	//	dfs(x,y,m,id,o);
	}
	else if(x>m&&y<=m)//左下 
	dfs(x-m,y,m,id+m*m,o);
	else if(x>m&&y>m)//右下 
	dfs(x-m,y-m,m,id+m*m*2,o);
	else
//	else if(x<=m&&y>m)//右上 
	{
		ll xx=x,yy=y-m;
		//	(m-x),-(m-y) 对应新的坐标 
		// -y ,x	逆时针 
		//(m-y), (m-x)//对应旋转和的新的坐标系
		// y,  x-2*m; 
		dfs(1+m-yy,m+1-xx,m,id+m*m*3,o);
	}
/*	else
	{
		puts("wa!!!!!");
	}*/
}
bool cmp(node a,node b)
{
	return a.id

 

F:比赛时wa了,没考虑到x==0和y==0的情况,这种情况线段树无法维护。。

我们只需要先把x,y同时加1即可

具体做法:

正常思路肯定时枚举横的三线,和竖的三线,找到最大,这样时n^2的复杂度。

一般二维的题目我们枚举一维,

 

比如枚举横三线,

先预处理竖三线,以每个y为三线的左线,求出三线包含的气球个数

然后枚举横坐标,算出以当前横坐标为底线的三线包含气球个数,由于这一会重复,我们把这三线上的气球

对竖三线造成的影响减去,再去最大值就行。

最后不要忘了把减去的影响加回来就行了。

//KX
#include 
using namespace std;
typedef long long ll;
typedef double db;
const int M= 1e6+7;
#define m (l+r)/2
#define ls o*2
#define rs o*2+1
int st[M<<2];
int sx[M],sy[M];
int sumx[M],sumy[M];
vectorvx[M];
void bd(int o,int l,int r)
{
	if(l==r)
	{
		st[o]=sy[l];
		return;
	}
	bd(ls,l,m);
	bd(rs,m+1,r);
	st[o]=max(st[ls],st[rs]);
}
void up(int o,int l,int r,int x,int d)
{
	if(l==r)
	{
		st[o]+=d;
		return ;
	}
	if(x<=m)up(ls,l,m,x,d);
	else up(rs,m+1,r,x,d);
	st[o]=max(st[ls],st[rs]);
}
int main()
{
	int n,r,x,y,mx=0,my=0;
	scanf("%d%d",&n,&r);
	for(int i=1;i<=n;i++)
	{
		scanf("%d%d",&x,&y);
		x++,y++;
		mx=max(mx,x),my=max(my,y);
		vx[x].push_back(y);
		sumx[x]++;sumy[y]++;
	}
	for(int i=1;i<=my;i++)
		sy[i]+=sumy[i]+sumy[i+r]+sumy[i+2*r];
		
	bd(1,1,my);
	int ma=0;
	for(int i=1;i<=mx;i++)
	{
		int now=0;
		//now+=sumx[i]+sumx[i+r]+sumx[i+2*r];
		int l1=vx[i].size(),l2=vx[i+r].size(),l3=vx[i+2*r].size();
		for(int j=0;j0)up(1,1,my,y-r,-1);
			if(y-2*r>0)up(1,1,my,y-2*r,-1);
		}
		for(int j=0;j0)up(1,1,my,y-r,-1);
			if(y-2*r>0)up(1,1,my,y-2*r,-1);
		}
		for(int j=0;j0)up(1,1,my,y-r,-1);
			if(y-2*r>0)up(1,1,my,y-2*r,-1);
		}
	//	printf("%d  %d   %d\n",i,st[1],now);
		ma=max(ma,st[1]+now);
		for(int j=0;j0)up(1,1,my,y-r,1);
			if(y-2*r>0)up(1,1,my,y-2*r,1);
		}
		for(int j=0;j0)up(1,1,my,y-r,1);
			if(y-2*r>0)up(1,1,my,y-2*r,1);
		}
		for(int j=0;j0)up(1,1,my,y-r,1);
			if(y-2*r>0)up(1,1,my,y-2*r,1);
		}
	}
	printf("%d\n",ma);
   	return 0;
}


 

你可能感兴趣的:(多校----牛客/hdu)