题目链接

问题分析

参照数据范围,我们需要一个能够在\(O(n\log n)\)复杂度内维护有序数列的数据结构。那么平衡树是很好的选择。参考程序中使用带旋Treap。

参考程序

#pragma GCC optimize( 3 )
#include <cstdio>
#include <ctime>
#include <algorithm> namespace Treap {
struct member {
int Number, Time;
bool operator > ( const member Other ) const {
return Number < Other.Number || Number == Other.Number && Time > Other.Time;
};
bool operator == ( const member Other ) const {
return Number == Other.Number && Time == Other.Time;
};
bool operator < ( const member Other ) const {
return Number > Other.Number || Number == Other.Number && Time < Other.Time;
}
};
struct node {
int Random, Size, Cnt;
member Value;
node *LeftChild, *RightChild;
};
void Collect( node *A ) {
A->Size = A->Cnt + ( ( A->LeftChild != NULL ) ? A->LeftChild->Size : 0 ) + ( ( A->RightChild != NULL ) ? A->RightChild->Size : 0 );
return;
}
node *LeftRotate( node *A ) {
node *B = A->RightChild; A->RightChild = B->LeftChild; B->LeftChild = A; Collect( A ); Collect( B ); return B;
}
node *RightRotate( node *A ) {
node *B = A->LeftChild; A->LeftChild = B->RightChild; B->RightChild = A; Collect( A ); Collect( B ); return B;
}
node *Insert( node *Rt, member x ) {
if( Rt == NULL ) {
Rt = new node;
Rt->Random = rand() % 1000000000; Rt->Value = x; Rt->Size = 1; Rt->Cnt = 1; Rt->LeftChild = Rt->RightChild = NULL;
return Rt;
}
++( Rt->Size );
if( Rt->Value == x ) { ++( Rt->Cnt ); return Rt; }
if( Rt->Value < x ) {
Rt->RightChild = Insert( Rt->RightChild, x ); if( Rt->RightChild->Random < Rt->Random ) Rt = LeftRotate( Rt );
} else {
Rt->LeftChild = Insert( Rt->LeftChild, x ); if( Rt->LeftChild->Random < Rt->Random ) Rt = RightRotate( Rt );
}
return Rt;
}
node *Del( node *Rt, member x ) {
if( Rt == NULL ) { printf( "No such number called %d\n", x ); return Rt; }
if( Rt->Value == x ) {
if( Rt->Cnt > 1 ) { --( Rt->Cnt ); --( Rt->Size ); return Rt; }
if( Rt->LeftChild == NULL ) { node *T = Rt->RightChild; delete Rt; return T; }
if( Rt->RightChild == NULL ) { node *T = Rt->LeftChild; delete Rt; return T; }
if( Rt->LeftChild->Random <= Rt->RightChild->Random ) {
Rt = RightRotate( Rt ); --( Rt->Size ); Rt->RightChild = Del( Rt->RightChild, x ); return Rt;
} else {
Rt = LeftRotate( Rt ); --( Rt->Size ); Rt->LeftChild = Del( Rt->LeftChild, x ); return Rt;
}
return Rt;
}
--( Rt->Size );
if( Rt->Value < x ) { Rt->RightChild = Del( Rt->RightChild, x ); return Rt; }
else { Rt->LeftChild = Del( Rt->LeftChild, x ); return Rt; }
return Rt;
}
int QueryR( node *Rt, member x ) {
int Ans = 0;
for( ; Rt != NULL; ) {
if( Rt->Value == x ) return Ans + ( ( Rt->LeftChild != NULL ) ? Rt->LeftChild->Size : 0 ) + 1;
if( Rt->Value < x ) {
Ans += ( ( Rt->LeftChild != NULL ) ? Rt->LeftChild->Size : 0 ) + Rt->Cnt;
Rt = Rt->RightChild;
} else Rt = Rt->LeftChild;
}
return Ans + 1;
}
member QueryN( node *Rt, int x ) {
for( ; Rt != NULL; ) {
int Rc = 0; if( Rt->LeftChild != NULL ) Rc = Rt->LeftChild->Size;
if( x > Rc && x <= Rc + Rt->Cnt ) return Rt->Value;
if( x <= Rc ) Rt = Rt->LeftChild; else { x -= Rc + Rt->Cnt; Rt = Rt->RightChild; }
}
printf( "QueryNumber Failed.\n" );
return ( member ){ -1, -1 };
}
member pre( node *Rt, member x ) {
member Ans = x;
for( ; Rt != NULL; ) if( Rt->Value < x ) { Ans = Rt->Value; Rt = Rt->RightChild; } else Rt = Rt -> LeftChild;
if( Ans == x ) printf( "Query Pre Failed.\n" );
return Ans;
}
member suc( node *Rt, member x ) {
member Ans = x;
for( ; Rt != NULL; ) if( Rt->Value > x ) { Ans = Rt->Value; Rt = Rt->LeftChild; } else Rt = Rt -> RightChild;
if( Ans == x ) printf( "Query Suc Failed.\n" );
return Ans;
}
struct treap {
node *Root;
void clear() { delete [] Root; Root = NULL; srand( time( NULL ) ); return; }
void insert( member x ) { Root = Insert( Root, x ); return; }
void Delete( member x ) { Root = Del( Root, x ); return; }
int QueryRank( member x ) { return QueryR( Root, x ); }
member QueryNumber( int x ) { return QueryN( Root, x ); }
member Pre( member x ) { return pre( Root, x ); }
member Suc( member x ) { return suc( Root, x ); }
};
} //Treap Treap::treap Tree; namespace UI {
typedef unsigned int ui ;
ui randNum( ui& seed , ui last , const ui m){
seed = seed * 17 + last ; return seed % m + 1;
}
ui seed, last = 7;
void InSeed() { scanf( "%llu", &seed ); return; }
} //UI const int Maxm = 100010;
Treap::member Rec[ Maxm ]; void MAIN() {
Tree.clear();
int n, m; scanf( "%d%d", &m, &n ); UI::InSeed();
for( int i = 1; i <= m; ++i ) {
Tree.insert( ( Treap::member ){ 0, 0 } );
Rec[ i ] = ( Treap::member ){ 0, 0 };
}
for( int i = 1; i <= n; ++i ) {
int x = UI::randNum( UI::seed, UI::last, m );
int y = UI::randNum( UI::seed, UI::last, m );
Tree.Delete( Rec[ x ] );
++Rec[ x ].Number;
Rec[ x ].Time += y;
Tree.insert( Rec[ x ] );
UI::last = Tree.QueryRank( Rec[ x ] ) - 1;
printf( "%llu\n", UI::last );
}
return;
} int main() {
int TestCases; scanf( "%d", &TestCases );
for( ; TestCases--; ) MAIN();
return 0;
}

最新文章

  1. YYModel 源码解读(二)之NSObject+YYModel.h (5)
  2. MVC4做网站后台:模块管理1、修改模块信息
  3. C# RSA 分段加解密
  4. 使用aspose.cell导出excel需要注意什么?
  5. Android开发-API指南-AIDL
  6. 浅度围观SBJson
  7. google浏览器的安装
  8. React中使用CSSTransitionGroup插件实现轮播图
  9. 重新认识JavaScript里的创建对象(一)
  10. 【Android Developers Training】 1. 创建一个Android项目工程
  11. nginx + rtmp 搭建流媒体服务器
  12. 2018 python面试题
  13. 面试官问我,使用Dubbo有没有遇到一些坑?我笑了。
  14. 从MFQ方法到需求分析
  15. hbase和zookeeper的安装和部署
  16. 发布程序时出现“类型ASP.global_asax同时存在于...”错误的解决办法
  17. 实现liunx之间无密码访问——ssh密匙
  18. postgresql----ANY/SOME&amp;&amp;ALL
  19. 【Linux学习笔记】Linux C中内联汇编的语法格式及使用方法(Inline Assembly in Linux C)
  20. Do the Untwist(模拟)

热门文章

  1. Fiddler--模拟弱网
  2. ORM中的锁和事务
  3. Hadoop单机模式/伪分布式模式/完全分布式模式
  4. springboot JPA mysql
  5. oracle 重置密码(一般电网,国企需要的二级等保)
  6. 剑指offer-和为S的两个数字-知识迁移能力-python
  7. RBAC(基于角色的访问控制)用户权限管理数据库设计
  8. yii的多表查询
  9. 02 Redis防止入侵
  10. Python基础教程之dict和set