线段树优化查找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);
#endif
while( 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;
}