码迷,mamicode.com
首页 > 其他好文 > 详细

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

时间:2017-07-18 16:51:32      阅读:189      评论:0      收藏:0      [点我收藏+]

标签:scan   void   push   题目   problem   blank   node   std   get   

题目链接

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

#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环的复仇(线段树)

标签:scan   void   push   题目   problem   blank   node   std   get   

原文地址:http://www.cnblogs.com/Just--Do--It/p/7200898.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!