Timus OJ 题目1521. War Games 2(SBT or 线段树解决约瑟夫环)

深入探讨游戏引擎、Unity、Cocos2dX等在游戏开发领域的应用与实践,涵盖动画、AR、VR等技术,以及游戏程序、美术和策划的相关内容。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1521. War Games 2

Time limit: 1.0 second
Memory limit: 64 MB

Background

During the latest war games (this story is fully described in the problem  "War games") the Minister of Defense of the Soviet Federation comrade Ivanov had a good chance to make sure personally, that an alertness of the Soviet Army under his command is just brilliant. But there was a thing, that continued to worry him. Being an outstanding commander, he realized, that only physical conditions of the soldiers were demonstrated. So the time came to organize one more war games and examine their mental capacity.
General Rascal was appointed to be responsible for the war games again. The general donated the allocated funds to the poor and went to bed free-hearted. In his dream, the tactics manual appeared to him and described a scheme, that allows to organize the war games absolutely free of charge.

Problem

In accordance with this scheme, the war games are divided into  N phases; and  N soldiers, successively numbered from 1 to  N, are marching round a circle one after another, i.e. the first follows the second, the second follows the third, ..., the ( N-1)-th follows the  N-th, and the  N-th follows the first. At each phase, a single soldier leaves the circle and goes to clean the WC, while the others continue to march. At some phase, the circle is left by a soldier, who is marching  Kpositions before the one, who left the circle at the previous phase. A soldier, whose number is  K, leaves the circle at the first phase.
Surely, Mr. Rascal cherished no hope about his soldiers' abilities to determine an order of leaving the circle. "These fools can not even paint the grass properly", - he sniffed scornfully and went to sergeant Filcher for an assistance.

Input

The only line contains the integer numbers  N (1 ≤  N ≤ 100000) and  K (1 ≤  K ≤  N).

Output

You should output the numbers of soldiers as they leave the circle. The numbers should be separated by single spaces.

Sample

input output
5 3
3 1 5 2 4
Problem Author: Ilya Grebnov, Nikita Rybak, Dmitry Kovalioff
Problem Source: Timus Top Coders: Third Challenge

Tags: data structures  (

hide tags for unsolved problems
)

用了两种写法都过了

一种是SBT的,一种线段树利用区间和的

SBT版本ac代码

156ms 1776kb

#include<stdio.h>
#include<string.h>
#define INF 0xfffffff
struct s    
{    
    int key,left,right,size;    
}tree[100100];    
int top,root;    
void left_rot(int &x)  
{    
    int y=tree[x].right;    
    tree[x].right=tree[y].left;    
    tree[y].left=x;    
    tree[y].size=tree[x].size;    
    tree[x].size=tree[tree[x].left].size+tree[tree[x].right].size+1;    
    x=y;    
}    
void right_rot(int &x)  
{    
    int y=tree[x].left;    
    tree[x].left=tree[y].right;    
    tree[y].right=x;    
    tree[y].size=tree[x].size;    
    tree[x].size=tree[tree[x].left].size+tree[tree[x].right].size;    
    x=y;    
}    
void maintain(int &x,bool flag)     
{    
    if(flag==false)  
    {    
        if(tree[tree[tree[x].left].left].size>tree[tree[x].right].size)  
            right_rot(x);    
        else  
            if(tree[tree[tree[x].left].right].size>tree[tree[x].right].size)    
            {    
                left_rot(tree[x].left);    
                right_rot(x);       
            }    
            else  
                return;    
    }    
    else  
    {    
        if(tree[tree[tree[x].right].right].size>tree[tree[x].left].size)  
            left_rot(x);    
        else  
            if(tree[tree[tree[x].right].left].size>tree[tree[x].left].size)  
            {    
                right_rot(tree[x].right);    
                left_rot(x);    
            }    
            else  
                return;    
    }    
    maintain(tree[x].left,false);    
    maintain(tree[x].right,true);    
    maintain(x,true);    
    maintain(x,false);    
}    
void insert(int &x,int key)    
{    
    if(x==0)    
    {    
        x=++top;    
        tree[x].left=0;    
        tree[x].right=0;    
        tree[x].size=1;    
        tree[x].key=key;    
    }    
    else  
    {    
        tree[x].size++;    
        if(key<tree[x].key)    
            insert(tree[x].left,key);    
        else  
            insert(tree[x].right,key);     
        maintain(x,key>=tree[x].key);    
    }    
}    
int remove(int &x,int key)  
{    
    tree[x].size--;    
    if(key>tree[x].key)    
        remove(tree[x].right,key);    
    else  
        if(key<tree[x].key)    
            remove(tree[x].left,key);    
        else  
            if(tree[x].left!=0&&tree[x].right==0)   
            {    
                int temp=x;    
                x=tree[x].left;    
                return temp;    
            }    
            else  
                if(!tree[x].left&&tree[x].right!=0)   
                {    
                    int temp=x;    
                    x=tree[x].right;    
                    return temp;    
                }    
                else  
                    if(!tree[x].left&&!tree[x].right)   
                    {    
                        int temp=x;    
                        x=0;    
                        return temp;    
                    }    
                    else  
                    {    
                        int temp=tree[x].right;    
                        while(tree[temp].left)    
                            temp=tree[temp].left;    
                        tree[x].key=tree[temp].key;    
                        remove(tree[x].right,tree[temp].key);    
                    }    
}    
int getmin(int x)    
{    
    while(tree[x].left)    
        x=tree[x].left;    
    return tree[x].key;    
}    
int getmax(int x)    
{    
    while(tree[x].right)    
        x=tree[x].right;    
    return tree[x].key;    
}    
int pred(int &x,int y,int key)    
{    
    if(x==0)  
    {  
        if(y==0)  
            return INF;  
        return tree[y].key;  
    }  
    if(key>tree[x].key)    
        return pred(tree[x].right,x,key);    
    else  
        return pred(tree[x].left,y,key);    
}    
int succ(int &x,int y,int key)    
{    
    if(x==0)  
    {  
        if(y==0)  
            return INF;  
        return tree[y].key;  
    }  
    if(key<tree[x].key)    
        return succ(tree[x].left,x,key);    
    else  
        return succ(tree[x].right,y,key);    
}
int get_min_k(int &x,int k)//閫夌k灏忕殑鏁�      
{    
    int r=tree[tree[x].left].size+1;    
    if(r==k)    
        return tree[x].key;    
    else   
        if(r<k)    
            return get_min_k(tree[x].right,k-r);    
        else   
            return get_min_k(tree[x].left,k);    
}  
int get_max_k(int &x,int k)  
{  
    int r=tree[tree[x].right].size+1;  
    if(r==k)  
        return tree[x].key;  
    else  
        if(r<k)  
            return get_max_k(tree[x].left,k-r);  
        else  
            return get_max_k(tree[x].right,k);  
}  
int main()
{
	int n,m;
	while(scanf("%d%d",&n,&m)!=EOF)
	{
		int i;
		top=root=0;
		for(i=1;i<=n;i++)
		{
			int x;
		//	scanf("%d",&x);
			insert(root,i);
		}
		int k=1;
		int flag=0;
		while(tree[root].size)
		{
			k=(k+m-1)%(tree[root].size);
			if(k==0)
				k=tree[root].size;
			int temp=get_min_k(root,k);
			remove(root,temp);
			if(flag)
				printf(" ");
			else
				flag=1;
			printf("%d",temp);
		}
		printf("\n");
	}
}
线段树版本

109ms 1776kb

ac代码

#include<stdio.h>
#include<string.h>
int node[100010<<2];
int ans=0;
void pushup(int tr)
{
	node[tr]=node[tr<<1|1]+node[tr<<1];
}
void build(int l,int r,int tr)
{
	node[tr]=r-l+1;
	if(l==r)
		return;
	int mid=(l+r)>>1;
	build(l,mid,tr<<1);
	build(mid+1,r,tr<<1|1);
}
int getsum(int L,int R,int l,int r,int tr)
{
	if(L<=l&&R>=r)
	{
		return node[tr];
	}
	int mid=(l+r)>>1;
	int ans=0;
	if(L<=mid)
		ans+=getsum(L,R,l,mid,tr<<1);
	if(R>mid)
		ans+=getsum(L,R,mid+1,r,tr<<1|1);
	return ans;
}
void remove(int pos,int l,int r,int tr)
{
	if(l==r)
	{
		node[tr]=0;
		ans=l;
		return;
	}
	int mid=(l+r)>>1;
	if(pos<=node[tr<<1])
		remove(pos,l,mid,tr<<1);
	else
		remove(pos-node[tr<<1],mid+1,r,tr<<1|1);
	pushup(tr);
}
int main()
{
	int n,m;
	while(scanf("%d%d",&n,&m)!=EOF)
	{
		int i,j,k=0;
		ans=0;
		build(1,n,1);
		for(i=0;i<n;i++)
		{
			if(ans==0)
				k=m%node[1];
			else
			{
				int ssum=getsum(1,ans,1,n,1);
				k=(ssum+m)%node[1];
			}
			if(k==0)
				k=node[1];
			remove(k,1,n,1);
			if(i)
				printf(" %d",ans);
			else
				printf("%d",ans);
		}
		printf("\n");
	}
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值