Who Gets the Most Candies?(线段树+单点更新)

来源:互联网 发布:摄影测量info软件 编辑:程序博客网 时间:2024/06/05 08:40

Who Gets the Most Candies?

Time Limit : 10000/5000ms (Java/Other)   Memory Limit : 262144/131072K (Java/Other)
Total Submission(s) : 33   Accepted Submission(s) : 13
Problem Description

N children are sitting in a circle to play a game.

The children are numbered from 1 to N in clockwise order. Each of them has a card with a non-zero integer on it in his/her hand. The game starts from the K-th child, who tells all the others the integer on his card and jumps out of the circle. The integer on his card tells the next child to jump out. Let A denote the integer. If A is positive, the next child will be the A-th child to the left. If A is negative, the next child will be the (A)-th child to the right.

The game lasts until all children have jumped out of the circle. During the game, the p-th child jumping out will get F(p) candies where F(p) is the number of positive integers that perfectly divide p. Who gets the most candies?

 

Input
There are several test cases in the input. Each test case starts with two integers <i>N</i> (0 < <i>N</i> <span lang="en-us">≤ 500,000) and <i>K</i> (1 ≤ <i>K</i> ≤ <i>N</i>) on the first line. The next <i>N</i> lines contains the names of the children (consisting of at most 10 letters) and the integers (non-zero with magnitudes within 10<sup>8</sup>) on their cards in increasing order of the children’</span>s numbers, a name and an integer separated by a single space in a line with no leading or trailing spaces.
 

Output
<p>Output one line for each test case containing the name of the luckiest child and the number of candies he/she gets. If ties occur, always choose the child who jumps out of the circle first.</p>
 

Sample Input
4 2Tom 2Jack 4Mary -1Sam 1
 

Sample Output
Sam 3
 

Source
PKU
 

Statistic | Submit | Back

题意:

第一行输入两个数n,k,分别代表n个人和一开始最先跳出的位置k,接下来输入n个人的名字和所拥有的数字num,这n个人顺时针坐在一圈,首先第k个人先出环,再当num为正数时顺时针走num步,那么数到的这个人就跳出环,以此类推,当num为负数时,逆时针走(-num)步,第m个跳出的人得m的不重复因子的个数(v )个糖果。求出得到得到最多的糖果的人,如果有多个一样的求最先跳出的,输出名子和得到糖果的数量.

思路:

线段树,先求出n个人中是第几个人跳出来得到的糖果最多,然后进行模拟,线段树的作用是线段树的节点中保存该区间剩下的人的个数,然后运用update进行删除操作,没update一次,删除一个人。

代码:

#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>using namespace std;#define L(rt) (rt<<1)#define R(rt) (rt<<1|1)const int N=500000;int n,id,maxx;//id用来记录最大的位置,maxx用来求最大的值int candy[N+5];struct person{    char name[15];    int num;}a[N+5];struct Tree{int l,r;int sum;//表示线段树节点中剩余的人的个数}p[4*N]; void go(){//计算因子,并求n范围内因子个数最多的一个数memset(candy,0,sizeof(candy));for(int i=1;i<=n;i++){candy[i]++;for(int j=i+i;j<=n;j+=i)candy[j]++;}maxx=candy[1];id=1;for(int i=2;i<=n;i++)if(candy[i]>maxx){maxx=candy[i];id=i;} }void build(int l,int r,int pos){    p[pos].l=l;    p[pos].r=r;    p[pos].sum=r-l+1;    if(l==r)return;    int mid=(l+r)>>1;    build(l,mid,L(pos));    build(mid+1,r,R(pos)); }int update(int k,int pos){p[pos].sum--;if(p[pos].l==p[pos].r){return p[pos].l;}if(p[L(pos)].sum>=k)return update(k,L(pos));elsereturn update(k-p[L(pos)].sum,R(pos));}int main(){ios::sync_with_stdio(false);int i,k;while(cin>>n>>k){go();   //一开始这个函数调用的位置出现错误,wa了两发for(i=1;i<=n;i++){cin>>a[i].name>>a[i].num;}build(1,n,1);int maxn=id;int tid;for(i=0;i<maxn;i++){n--;tid=update(k,1);//原始的位置if(n==0)break;if(a[tid].num>0)//表示左起k=(k-1+a[tid].num-1)%n+1; //下一次跳出环的人的编号else//表示右起k=((k-1+a[tid].num)%n+n)%n+1;}cout<<a[tid].name<<' '<<maxx<<endl;}     return 0;}


阅读全文
0 0
原创粉丝点击