版权声明:转载请联系作者 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:代码就不改了,放在这里,警醒自己(才不是因为懒)