2886

/*
线段树

需要用到求一个数的约数个数,这个需要打个表吧

此处的表,是借用了别人。因为我只是想学习下线段树,偷懒了下 

这线段树,其实也没什么特别的,重要的是如何构造线段树的保存的值。就想网络流,二分匹配的算法似的
本身没什么特别的,但是构图很重要,比算法本身重要
*/
// include file
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <cctype>
#include <ctime>

#include <iostream>
#include <sstream>
#include <fstream>
#include <iomanip>
#include <bitset>

#include <algorithm>
#include <string>
#include <vector>
#include <queue>
#include <set>
#include <list>
#include <functional>

using namespace std;

// typedef
typedef long long LL;
typedef unsigned long long ULL;

// 
#define read freopen("in.txt","r",stdin)
#define write freopen("out.txt","w",stdout)

#define Z(a) (a<<1)
#define Y(a) (a>>1)

const double eps = 1e-6;
const double INFf = 1e100;
const int INFi = 1000000000;
const LL INFll = (LL)1<<62;
const double Pi = acos(-1.0);

template<class T> inline T sqr(T a){return a*a;}
template<class T> inline T TMAX(T x,T y)
{
	if(x>y) return x;
	return y;
}
template<class T> inline T TMIN(T x,T y)
{
	if(x<y) return x;
	return y;
}
template<class T> inline T MMAX(T x,T y,T z)
{
	return TMAX(TMAX(x,y),z);
}
template<class T> inline T MMIN(T x,T y,T z)
{
	return TMIN(TMIN(x,y),z);
}
template<class T> inline void SWAP(T &x,T &y)
{
	T t = x;
	x = y;
	y = t;
}


// code begin

struct node
{
	char name[12];
	int card;
};
node data[500010];

struct seg_tree_node
{
	int left,right;  // 左右编号
	int remain;
};
seg_tree_node mem[1050010];
int N,K;

void buildSegtree(int l,int r,int dx=1)
{
	mem[dx].left = l;
	mem[dx].right = r;
	mem[dx].remain = r-l+1;
	//printf("%d\n",dx);
	if(l==r) return;
	buildSegtree(l,Y(l+r),Z(dx));
	buildSegtree(Y(l+r)+1,r,Z(dx)+1);
}

int query(int pos,int dx=1) //第pos位置小孩要出局了,那么要更新局面了
{
	if(mem[dx].left==mem[dx].right)
	{
		--mem[dx].remain;
		return mem[dx].left;
	}
	int zson = Z(dx),yson =Z(dx)+1;
	int left = mem[zson].remain;
	int right = mem[yson].remain;
	--mem[dx].remain;
	if(pos>left)
	{
		return query(pos-left,yson);
	}
	else
	{
		return query(pos,zson);
	}
}


const int PV[40] = {1,2,4,6,12,24,36,48,60,120,180,240,360,720,840,1260,1680,2520,5040,7560,10080,15120,20160,25200,27720,45360,50400,55440,83160,110880,166320, 221760, 277200, 332640, 498960, 554400, 665280};
const int Nu[40] = {1, 2, 3, 4, 6, 8, 9, 10, 12, 16, 18, 20, 24, 30, 32, 36, 40, 48, 60, 64, 72, 80, 84, 90, 96, 100, 108, 120, 128, 144, 160, 168, 180, 192, 200, 216, 224};


int main()
{	
	int pre,findit,ans[2];
	read;
	write;

	while(scanf("%d %d",&N,&K)==2)
	{
		//getchar();
		for(int i=0;i<N;i++)
		{
			//gets(in);
			scanf("%s %d",data[i].name,&data[i].card);
		}
		
		buildSegtree(0,N-1);
		pre = K;
		for(int i=0;i<40;i++)
		{
			if(PV[i]>N) break;
			ans[0] = PV[i];
			ans[1] = Nu[i];
		}
		for(int i=1;i<=N;i++) //总共循环N次,最后一次找到的就是那个孩子的编号了。
		{
			//之前的是找到第pre个小孩子
			findit = query(pre);    // 然后在最新的情况下找下个的坐标
			
			//printf("找到的下标编号: %d %d\n",pre,findit);
			if(i==ans[0])
			{
				ans[0] = findit;
				break;
			}
			if(i==N) break;
			//根据findit找一下个pre
			if( data[findit].card>0 )
			{
				pre = (pre-1+(data[findit].card-1)%(N-i))%(N-i)+1;
			}
			else
			{
				pre = (pre-1+N-i+(data[findit].card)%(N-i) )%(N-i)+1; //这里出现问题
			}
		}
		printf("%s %d\n",data[ans[0]].name,ans[1]);
	}
	return 0;
}

posted @ 2011-04-13 23:40  AC2012  阅读(206)  评论(0编辑  收藏  举报