POJ-2886 Who Gets the Most Candies? 线段树 + 反素数

来源:互联网 发布:java 深度遍历二叉树 编辑:程序博客网 时间:2024/05/22 02:10

题目链接


线段树优化查找i-d-1的最大子序列长度

#include<stdio.h>#include<iostream>#include<string>#include<string.h>#include<math.h>#include<functional>#include<algorithm>#include<vector>#include<queue>using namespace std;const int maxn = 500100;const int inf = 1<<30;//0x7f;int n,k;char name[maxn][11];  int val[maxn];  struct node{int sum;}tree[maxn<<2];// a为反素数表,b为对应的约数个数int a[37]={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,500001};  int b[37]={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,1314521};  void buildtree( int rt,int ld,int rd ){tree[rt].sum = rd-ld+1;if( ld < rd ){int mid = (ld +rd)>>1;buildtree( rt<<1,ld,mid );buildtree( rt<<1|1,mid+1,rd );}}int query( int rt,int ld,int rd,int id ){tree[rt].sum --;if( ld == rd )return ld;int mid = (ld+rd)>>1;if( id <= tree[rt<<1].sum )return query( rt<<1,ld,mid,id );return query( rt<<1|1,mid+1,rd,id-tree[rt<<1].sum );}int main() {#ifndef ONLINE_JUDGE    freopen("data.txt","r",stdin);#endifwhile( scanf("%d %d",&n,&k) != EOF ){int i = 0, Max = 0, p = 0,num = n; // 第p个出去的孩子得到最多的糖果,为Max         while (a[i] <= n)              i++;          p = a[i-1];          Max = b[i-1];          buildtree( 1,1,n );          for( i = 1; i <= n; i ++ )              scanf("%s %d", &name[i], &val[i]);          k --;                    //模拟        int idx; // idx为当前出去的孩子的原始位置          for( i = 0; i < p; i ++ ){ // 只要求出第p个出去的孩子即可             num --;              idx = query( 1,1,n,k+1 );              if( i == p-1 )break;              if ( val[idx] > 0 )                  k = (k+val[idx]-1)%num;              else                  k = ((k+val[idx])%num+num)%num;          }          printf("%s %d\n", name[idx], Max);      }      return 0;}


0 0