POJ 2886 Who Gets the Most Candies? 线段树
2012-06-30 22:32
549 查看
http://poj.org/problem?id=2886
题意:
N个人玩一个游戏,每个人都有一个weight ,游戏从第K个人开始,第一轮标号为K的人退出游戏,下一个退出的人的编号由上一轮退出的人的weight决定,如果上一轮退出的人的weight
为正,则下一个退出的人是上一轮退出的人的左手边的第weight个人,如果是负数则是右手边
的第weight个人,每个人退出时候都有一个得分,得分是退出的编号的约数的个数,问得分最
高的人能得几分。 N <= 500.000
思路:
分析题目可以看出, 首先题目要求的是得分最高的人的得分,因此我们可以先预处理出所有编
号的得分,然后求出最大的得分,这样问题就变成求一个指定退出编号的人了。然后对于每个
人有一个weight, 现在我们要做的就是如何快速地从一个人求到另外一个人,这样我们可以利
用线段树来求,在N <= 500 000 的情况下, 这个可以在O( nlogn )的算法内求出。
代码:
题意:
N个人玩一个游戏,每个人都有一个weight ,游戏从第K个人开始,第一轮标号为K的人退出游戏,下一个退出的人的编号由上一轮退出的人的weight决定,如果上一轮退出的人的weight
为正,则下一个退出的人是上一轮退出的人的左手边的第weight个人,如果是负数则是右手边
的第weight个人,每个人退出时候都有一个得分,得分是退出的编号的约数的个数,问得分最
高的人能得几分。 N <= 500.000
思路:
分析题目可以看出, 首先题目要求的是得分最高的人的得分,因此我们可以先预处理出所有编
号的得分,然后求出最大的得分,这样问题就变成求一个指定退出编号的人了。然后对于每个
人有一个weight, 现在我们要做的就是如何快速地从一个人求到另外一个人,这样我们可以利
用线段树来求,在N <= 500 000 的情况下, 这个可以在O( nlogn )的算法内求出。
代码:
#include <stdio.h> #include <string.h> #define LL(a) ( (a)<<1 ) #define RR(a) ( (a)<<1|1 ) int N , K ; const int MAXN = 500010 ; char name[MAXN][11] ; int val[MAXN] ; int d_num[MAXN] ; int _max , pos ; int num[MAXN<<2] ; void cal(){ for(int i=1;i<MAXN;i++) d_num[i] = 1 ; for(int i=2;i<MAXN;i++){ for(int j=1;j*i<MAXN;j++){ d_num[ i*j ] ++ ; } } } void build(int l , int r , int idx ){ int mid = (l + r) >> 1 ; if(l == r){ num[idx] = 1 ; return ; } build(l , mid , LL(idx) ) ; build(mid+1, r , RR(idx) ) ; num[idx] = num[ LL(idx) ] + num[ RR(idx) ] ; } int query(int l ,int r, int idx , int a , int b){ if(l==a && r==b){ return num[idx] ; } int mid = (l + r) >> 1; if(b <= mid){ return query( l, mid, LL(idx) , a, b); } else if( mid < a ){ return query( mid+1 , r ,RR(idx) , a ,b ); } else{ return query( l ,mid ,LL(idx) , a , mid ) + query( mid+1, r, RR(idx) , mid+1, b ); } } void update1(int l,int r , int idx ,int pos){ if(l == r){ num[idx] -- ; return ; } int mid = (l + r) >> 1; if( pos <= mid ){ update1(l , mid , LL(idx) , pos ); } else{ update1(mid+1, r, RR(idx) , pos ); } num[idx] = num[ LL(idx) ] + num[ RR(idx) ] ; } int update(int l ,int r , int idx , int vv){ if(l == r){ return l ; } int mid = (l + r ) >> 1 ; if( num[ LL(idx) ] >= vv ){ return update(l ,mid , LL(idx) , vv); } else{ return update(mid+1, r , RR(idx) , vv-num[ LL(idx) ] ) ; } } void solve(){ int nn = 1 ; int now = K ; while( nn <= N ){ if(nn == pos){ printf("%s %d\n",name[now] , d_num[pos] ); return ; } int vv = val[now] ; int left = N - nn ; int n1 , n2 ; if( vv > 0 ){ // go left n1 = query(1, N , 1 , 1 , now ); update1(1 , N ,1 , now); n1 -- ; n2 = left - n1 ; vv %= left ; if( vv == 0 ){ if(n1 == 0) now = update(1 , N ,1 , left) ; else now = update(1, N ,1 , n1 ) ; } else{ if( vv <= n2 ){ vv = n1 + vv ; } else{ vv -= n2 ; } now = update(1, N , 1 , vv ); } } else{ // go right ; n1 = query(1 , N , 1 , 1 , now ) ; update1(1 , N ,1 , now); n1 -- ; n2 = left - n1 ; vv = -vv ; vv %= left ; if( vv == 0 ){ if( n2 == 0 ){ now = update(1 , N ,1 , 1 ); } else{ now = update(1 , N , 1 , n1 + 1 ); } } else{ if( vv <= n1 ){ now = update(1, N ,1 ,n1+1-vv); } else{ now = update(1 , N ,1 , left-(vv-n1)+1 ); } } } nn++ ; } } int main(){ cal() ; //freopen("1out.txt","w",stdout) ; while( scanf("%d %d",&N,&K) == 2){ for(int i=1;i<=N;i++){ scanf("%s %d",name[i] , val+i) ; } _max = -1 ; for(int i=1;i<=N;i++){ if( d_num[i] > _max ){ _max = d_num[i] ; pos = i ; } } build( 1, N ,1 ); solve() ; } return 0 ; }
相关文章推荐
- poj 2886 Who Gets the Most Candies?(线段树单点更新)
- POJ Who Gets the Most Candies? 2886(线段树)
- POJ 2886 Who Gets the Most Candies? (线段树)
- POJ2886-Who Gets the Most Candies?-模拟约瑟夫环+反素数表(线段树上二分+爆搜打表)
- POJ 2886 Who Gets the Most Candies? (线段树)
- POJ 2886 Who Gets the Most Candies? (打表+线段树)
- POJ 2886 Who Gets the Most Candies?(线段树模拟约瑟夫环,高合成数)
- poj 2886 Who Gets the Most Candies?(线段树)
- poj 2886 Who Gets the Most Candies?(线段树-单点更新)
- POJ 2886 Who Gets the Most Candies? (线段树 约瑟夫环问题变种)
- poj 2886 Who Gets the Most Candies?(线段树、反素数)
- POJ 2886 Who Gets the Most Candies? [线段树-单点更新]【数据结构】
- POJ 2886 Who Gets the Most Candies?(线段树 + 约瑟夫环 + 反素数)
- POJ 2886 Who Gets the Most Candies? 线段树
- (中等) POJ 2886 Who Gets the Most Candies? , 反素数+线段树。
- POJ-2886-Who Gets the MostCandies?-(线段树)
- POJ 2886 Who Gets the Most Candies? 线段树单点更新
- POJ 2886 Who Gets the Most Candies?(线段树)
- POJ 2886 Who Gets the Most Candies?【线段树单点更新+反素数打表】【好题】
- [poj 2886] Who Gets the Most Candies? 线段树