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

比赛 AC:  B,D,E,H

我过B,E.

补题情况:

---队友过的 且未补题

Ο 自己过的或赛后补题

题号ABCDEFGHIJKL
状态.Ο.---ΟΟ.---....

 

B:斐波那契数列

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

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

//KX
#include <bits/stdc++.h>
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<<i<<"--"<<a[i]<<endl;
	}
	s[1]=" COFFEE";
	s[2]=" CHICKEN";
	int t;
	cin>>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 <bits/stdc++.h>
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<b.id;
}
int main()
{
	ll n,k;
	scanf("%lld%lld",&n,&k);
	ll d=1<<k;
	//printf("%lld-----\n",d);
	for(int i=1;i<=n;i++)
	{
		scanf("%lld%lld",&P[i].x,&P[i].y);
		dfs(P[i].x,P[i].y,d,0,i);
	}
	sort(P+1,P+n+1,cmp);
	for(int i=1;i<=n;i++)
	{
		printf("%lld %lld\n",P[i].x,P[i].y);
	}
   	return 0;
}


/*
64 3
1 1
1 2
1 3
1 4
1 5
1 6
1 7
1 8
2 1
2 2
2 3
2 4
2 5
2 6
2 7
2 8
3 1
3 2
3 3
3 4
3 5
3 6
3 7
3 8
4 1
4 2
4 3
4 4
4 5
4 6
4 7
4 8
5 1
5 2
5 3
5 4
5 5
5 6
5 7
5 8
6 1
6 2
6 3
6 4
6 5
6 6
6 7
6 8
7 1
7 2
7 3
7 4
7 5
7 6
7 7
7 8
8 1
8 2
8 3
8 4
8 5
8 6
8 7
8 8
*/

 

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

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

具体做法:

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

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

 

比如枚举横三线,

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

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

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

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

//KX
#include <bits/stdc++.h>
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];
vector<int>vx[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;j<l1;j++)
		{
			now++;
			x=i;y=vx[x][j];
			up(1,1,my,y,-1);
			if(y-r>0)up(1,1,my,y-r,-1);
			if(y-2*r>0)up(1,1,my,y-2*r,-1);
		}
		for(int j=0;j<l2;j++)
		{
			now++;
			x=i+r;y=vx[x][j];
			up(1,1,my,y,-1);
			if(y-r>0)up(1,1,my,y-r,-1);
			if(y-2*r>0)up(1,1,my,y-2*r,-1);
		}
		for(int j=0;j<l3;j++)
		{
			now++;
			x=i+2*r;y=vx[x][j];
			up(1,1,my,y,-1);
			if(y-r>0)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;j<l1;j++)
		{
			x=i;y=vx[x][j];
			up(1,1,my,y,1);
			if(y-r>0)up(1,1,my,y-r,1);
			if(y-2*r>0)up(1,1,my,y-2*r,1);
		}
		for(int j=0;j<l2;j++)
		{
			x=i+r;y=vx[x][j];
			up(1,1,my,y,1);
			if(y-r>0)up(1,1,my,y-r,1);
			if(y-2*r>0)up(1,1,my,y-2*r,1);
		}
		for(int j=0;j<l3;j++)
		{
			x=i+2*r;y=vx[x][j];
			up(1,1,my,y,1);
			if(y-r>0)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;
}


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值