qdu校内排位赛- K 闪电鞭曲线 (分治-分形)

题目描述

在这里插入图片描述
在这里插入图片描述

思路

对于 k > 2 的图形都可以由(k-1)的图形转换过来,我们可以先得到(k-1)图形,然后推得k的图形(编号和坐标都要转换),具体看代码吧(我的代码真长,ybl大佬的代码短,可惜,我瓢不到啊/(ㄒoㄒ)/~~)(这就是蓝皮书算法竞赛进阶指南的分治里面的分形例题的变形)

代码
#include<iostream>
#include<string>
#include<map>
#include<set>
//#include<unordered_map>
#include<queue>
#include<cstdio>
#include<vector>
#include<cstring>
#include<algorithm>
#include<iomanip>
#include<cmath>
#include<fstream>
#define X first
#define Y second
#define best 131 
#define INF 0x3f3f3f3f
#define pii pair<int,int>
#define lowbit(x) x & -x
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const double eps=1e-7;
const double pai=acos(-1.0);
const int N=2e4+10;
const int maxn=1e5+10;
const int mod=1e9+7;
ll dfs1(ll x,ll y,ll t)
{
	if(t==1)
	{
		if(x==1&&y==1) return 1;
		if(x==2&&y==1) return 2;
		if(x==2&&y==2) return 3;
		if(x==1&&y==2) return 4;
	}
	ll pos=2<<(t-2);
	if(x<=pos&&y<=pos) //左上 
		return dfs1(y,x,t-1);
	else if(x>pos&&y>pos) //右下 
		return pos*pos*2+dfs1(x-pos,y-pos,t-1);
	else if(x<=pos&&y>pos) //右上 
		return pos*pos*3+dfs1(2*pos+1-y,pos+1-x,t-1);
	else if(x>pos&&y<=pos) //左下 
		return pos*pos+dfs1(x-pos,y,t-1);
}
pii dfs2(ll id,ll t,ll flag)
{
	pii tmp;
	if(t==1)
	{
		if(id==1) tmp.first=1,tmp.second=1;
		else if(id==2) tmp.first=2,tmp.second=1;
		else if(id==3) tmp.first=2,tmp.second=2;
		else if(id==4) tmp.first=1,tmp.second=2;
		if(flag==1)
			swap(tmp.first,tmp.second);
		else if(flag==4)
		{
			ll xx=tmp.first,yy=tmp.second;
			tmp.first=2+1-yy,tmp.second=2+1-xx;
	   	} 
		return tmp;
	}
	ll pos=2<<(t-2);
	if(id<=pos*pos)//左上 
	{
		tmp=dfs2(id,t-1,1);
		tmp.first+=0,tmp.second+=0; 
	}
	else if(id>pos*pos&&id<=pos*pos*2)//左下 
	{
		tmp=dfs2(id-pos*pos,t-1,2);
		tmp.first+=pos,tmp.second+=0;
	} 
	else if(id>pos*pos*2&&id<=pos*pos*3)//右下 
    {
	    tmp=dfs2(id-pos*pos*2,t-1,3);
        tmp.first+=pos,tmp.second+=pos;
	}
	else if(id>pos*pos*3)//右上
	{
		tmp=dfs2(id-pos*pos*3,t-1,4);
    	tmp.first+=0,tmp.second+=pos;
    }
	if(flag==1) swap(tmp.first,tmp.second);
	else if(flag==4)
	{
	    ll xx=tmp.first,yy=tmp.second;
		tmp.first=pos*2+1-yy,tmp.second=pos*2+1-xx;	
	}
	return tmp;
}
int main()
{
	ll n,k;
	scanf("%lld%lld",&n,&k);
	while(n--)
	{
		ll op,x,y;
		scanf("%lld%lld%lld",&op,&x,&y);
		if(op==1)
			printf("%lld\n",dfs1(x,y,k));
	    else
	    {
	    	pii p1=dfs2(x,k,2);
	    	pii p2=dfs2(y,k,2);
	    	ll dis=abs(p1.first-p2.first)+abs(p1.second-p2.second);
			printf("%lld\n",dis); 
		}
	} 
    return 0;
}




评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值