xdu_1009: Josephus环的复仇(线段树)

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了xdu_1009: Josephus环的复仇(线段树)相关的知识,希望对你有一定的参考价值。

题目链接

题意不难理解,解法具体看代码及注释吧。。

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;

const int maxn=2e5+7;
int n,k;
int ql,qr;
int pos; //当前要出队的人在剩余人中排在第几靠左的地方 

struct node
{
    int l,r;
    int pre;    //记录区间中剩余的最靠右的人在所有剩余人中的位置 
    int lz;        //lazy标记 
} a[maxn<<2];

void push_up(int rt)
{
    a[rt].pre=max(a[rt<<1].pre,a[rt<<1|1].pre);
}
void build(int rt,int l,int r)
{
    a[rt].l=l,a[rt].r=r;
    if(l==r)
    {
        a[rt].pre=l;
        return ;
    }
    int mid=(l+r)>>1;
    build(rt<<1,l,mid);
    build(rt<<1|1,mid+1,r);
    push_up(rt); 
}
void update(int rt)
{
    int l=a[rt].l,r=a[rt].r;
    if(ql<=l&&r<=qr)
    {
        --a[rt].pre;
        --a[rt].lz;
        return ;
    }
    int mid=(l+r)>>1;
    if(ql<=mid) update(rt<<1);
    if(qr>mid)  update(rt<<1|1);
    push_up(rt);
}
void push_down(int rt)
{
    int& lz=a[rt].lz;
    if(lz==0) return ;
    a[rt<<1].lz+=lz;
    a[rt<<1|1].lz+=lz;
    a[rt<<1].pre+=lz;
    a[rt<<1|1].pre+=lz;
    lz=0;
}
int query(int rt)
{
    int l=a[rt].l,r=a[rt].r;
    if(l==r) return l;
    push_down(rt);
    int mid=(l+r)>>1;
    if(a[rt<<1].pre>=pos) return query(rt<<1);
    else return query(rt<<1|1);
}

int main()
{
    scanf("%d%d",&n,&k);
    build(1,1,n);
    int cnt=n;
    pos=1;
    for(int i=0;i<n;i++)
    {
        pos=(pos-2+k+cnt*2)%cnt+1;    //当前位置变更 
        --cnt;    //少了个人 
        int p=query(1);        //出队人在原队伍中的位置 
        printf("%d%c",p,i==n-1? \n: );
        ql=p,qr=n;            //出队后,pre发生变化的区间范围 
        update(1);
    }
}

 

以上是关于xdu_1009: Josephus环的复仇(线段树)的主要内容,如果未能解决你的问题,请参考以下文章

小朋友学数据结构:约瑟夫环的链表解法数组解法和数学公式解法

集训实录2018_XDU_ACM_SUMMER_TRAINING

XDU_1064:Desolator in RA2

CF1009F Dominant Indices [线段树合并]

HAOI2017 八纵八横——线段树分治+线性基

XDU1019 阶乘因子的个数