比赛 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;
}