XDOJ1009 Josephus环的复仇

版权声明:转载请联系作者 https://blog.csdn.net/xiaoshikjj/article/details/82025324

   题目

不知道是什么玄学,用了结构体储存了左右端点,但在update,query函数中却不得不使用l,r做参数,储存的东西没法用??

头秃。。。

看了别人的题解,感觉有点桶排序的意思。

每次记录到这个节点下(它的子子孙孙)有几个叶子结点(如果是叶子结点就是一个),每次出列后叶子结点清零,update更新维护一下。

代码:

#include<algorithm>
#include<stdio.h>
#include<string.h>
#define N 200010
using namespace std;
int b[N];
struct node
{
	int l,r,date;
}a[N*4];
int n;
void build(int p,int l,int r)
{
	if(l==r)
	{
		a[p].l=l;a[p].r=r;a[p].date=1;
		return;
	}
	int mid=(l+r)/2;
	build(p+p,l,mid);
	build(p+p+1,mid+1,r);
	a[p].l=a[p+p].l;a[p].r=a[p+p+1].r;
	a[p].date=a[p+p].date+a[p+p+1].date;
}
void update(int p,int l,int r,int aa)
{
	int mid=(l+r)/2;
	if(l==aa&&r==aa)
	{
		a[p].date=0;return;//改变叶子结点的值(此点出列) 
	}
	if(aa>mid) update(p+p+1,mid+1,r,aa);
	else update(p+p,l,mid,aa);
	a[p].date=a[p+p].date+a[p+p+1].date;
}
int sum;
void query(int p,int l,int r,int aa)
{
	int mid=(l+r)/2;	
	if(l==r)
	{
		sum=a[p].r;
		//printf("\n%d%d%d%d\n",l,r,a[p].l,a[p].r);
		return;//找到叶子结点,sum 为节点的端点,即为绝对位置 
	}
	if(aa<=a[p+p].date) query(p+p,l,mid,aa);//aa为相对位置,与当前节点的左儿子比较决定向哪边查询 
	if(aa>a[p+p].date) query(p+p+1,mid+1,r,aa-a[p+p].date);//左儿子已经有的不去管,只找还需要多少 
}
int main()
{
	int k;
	scanf("%d%d",&n,&k);
	for(int i=1;i<=n;i++) b[i]=i;
	build(1,1,n);
	int p=k;
	for(int i=1;i<=n;i++)//第i次出列 
	{
		int aa=k%(n-i+1);//aa表示在当前情况下,出列的数是第几个(相对位置)? 
		if(aa==0) aa=(n-i+1);//k是(n-i+1)的整数倍时,出列的就是第k个 
		query(1,1,n,aa);//去查询绝对位置 
		if(i==1) printf("%d",b[sum]);
		else printf(" %d",b[sum]);
		update(1,1,n,sum);//更新
		aa+=(p-1);
		k=aa;//k的更新,每次一个数出列,下一个出列的数的相对位置向前一个单位,因此累加p-1,由于取余操作,不必担心k的大小 
	}
	return 0;
}

以下一个不知道错在哪里的代码(???)

#include<stdio.h>
using namespace std;
const int maxn=2e5+10;
struct node
{
	int l,r,num;//num记录[l,r]有几个数,权值线段树的思想 
}tree[maxn*4];
int b[maxn];
void build(int p,int l,int r)
{
	if(l==r)
	{
		tree[p].l=l;tree[p].r=r;
		tree[p].num=1;return;
	}
	int mid=(l+r)/2;
	build(p+p,l,mid);
	build(p+p+1,mid+1,r);
	tree[p].l=tree[p+p].l;tree[p].r=tree[p+p+1].r; 
	tree[p].num=tree[p+p].num+tree[p+p+1].num;
}
void update(int p,int aa)
{
	if(tree[p].l==aa&&tree[p].r==aa)
	{
		tree[p].num=0;return;
	}
	int mid=(tree[p].l+tree[p].r)/2;
	if(mid>=aa) update(p+p,aa);
	if(mid<aa) update(p+p+1,aa);
	tree[p].num=tree[p+p].num+tree[p+p+1].num;
}
int ans;
void query(int p,int aa)//节点这么用问题在哪?不该这么用?
{
	if(tree[p].l==tree[p].r)
	{
		ans=tree[p].l;
		printf("\n%d**\n",ans);
		return;
	}
	int mid=(tree[p].l+tree[p].r)/2;
	if(aa<=tree[p+p].num) query(p+p,aa);
	if(aa>tree[p+p].num) query(p+p+1,aa-tree[p+p].num);
}

int main()
{
	int n,k;
	scanf("%d%d",&n,&k);
	for(int i=1;i<=n;++i) b[i]=i;
	build(1,1,n);
	int p=k;
	for(int i=1;i<=n;i++)
	{
		int aa=k%(n-i+1);
		if(aa==0) aa=n-i+1;
		query(1,aa);
		if(i==1) printf("%d",b[ans]);
		else printf(" %d",b[ans]);
		update(1,aa);
		aa+=(p-1);
		k=aa;
	}
	return 0;
}
/*推测:结构体中储存的左右端点可能有些地方没记录到??,用l,r可能更全面??*/

欢迎大家与我讨论~

!!!!

更新,找到问题了!!!

我是ZZ。。。。

定位代码61行

那里的update(1,aa),aa?!我更新了个什么鬼?

aa只是出栈元素的的相对位置。。。

更改为update(1,ans)!!!

PS:代码就不改了,放在这里,警醒自己(才不是因为懒

猜你喜欢

转载自blog.csdn.net/xiaoshikjj/article/details/82025324