ZOJ 2112 Dynamic Rankings

这里是题目地址

 

其实就是带修改的区间第K大。

写了一下BIT套主席树,内存飞起,似乎需要特别的优化技巧 = = 所以还是写了一下线段树套平衡树,跑了1s左右。

其实线段树套平衡树就是归并树的自然扩展而已。

归并树是把归并排序的过程建成一颗线段树,每个节点是一个数组,存的是这个节点对应区间的元素的正序:

空间复杂度O( n log n ) 。

每次查询的时候二分答案, 问题转化成询问区间中有多少个数比k小。外层查询和一般的线段树一样,只是在线段树的节点处需要再次二分得到节点区间中比k小的数的个数。这样二分答案有一个log ,线段树中询问也需要一个log ,线段树节点处二分需要一个log ,每次询问的复杂度为O( log^3 n ) 。

 

加入修改操作的时候,只需要把线段树节点的数组改为平衡树实现就好了。这是很自然的,线段树节点维护对应节点的顺序,又要支持修改,显然平衡树符合要求。

平衡树用splay实现了一下跑了1080ms ,然后用Treap实现了一下RE得浑身难受。。。实在是码力不行啊Orz

  1 #include <iostream>
  2 #include <cstring>
  3 #include <cstdio>
  4 using namespace std ;
  5 const int N = 50000 +10 ,INF = ~1u>>1;
  6 int M ,num[N] ;
  7 struct node{
  8     node *ch[2] ,*p ;
  9     int size ,val ;
 10     bool d() ;
 11     void setc( node * ,bool ) ,rol() ,pushup() ;
 12 }pool[N*19] ,*cur ,NU ,*null = &NU ;
 13 bool node::d(){
 14     return p->ch[1] == this ;
 15 }
 16 void node::setc( node *c ,bool d ){
 17     ch[d] = c ,c->p = this ;
 18 }
 19 void node::rol(){
 20     node *s = p ;
 21     int dd = d() ;
 22     s->p->setc( this ,p->d() ) ;
 23     s->setc( ch[!dd] ,dd ) ;
 24     setc( s ,!dd ) ;
 25     s->pushup() ;
 26 }
 27 void node::pushup(){
 28     size = ch[0]->size + ch[1]->size + 1 ;
 29 }
 30 struct Splay{
 31     node *root ;
 32     void splay( node * ,node * ) ,insert( node * ) ;
 33     void change( int ,int ) ,find( int ) ,init() ;
 34     node *get( int ) ;
 35     int rank( int ) ;
 36 }tree[N<<2] ;
 37 
 38 node *newnode( int val ){
 39     cur->val = val ;
 40     cur->size = 1 ;
 41     cur->ch[0] = cur->ch[1] = cur->p = null ;
 42     return cur ++ ;
 43 }
 44 void Splay::init(){
 45     root = newnode(-INF) ;
 46 }
 47 void Splay::splay( node *x ,node *p = null ){
 48     while( x->p != p ){
 49         if( x->p->p != p )
 50             x->d() == x->p->d() ? x->p->rol() : x->rol() ;
 51         x->rol() ;
 52     }
 53     x->pushup() ;
 54     if( p == null ) root = x ;
 55 }
 56 void Splay::insert( node *x ){
 57     if( root == null ) root = x ,root->p = null ;
 58     else for( node *t = root ;; ){
 59         ++t->size ;
 60         node *&s = t->ch[ x->val > t->val ] ;
 61         if( s == null ){
 62             s = x ,s->p = t ;
 63             splay( x ) ;
 64             break ;
 65         }
 66         t = s ;
 67     }
 68 }
 69 void Splay::find( int x ){
 70     for( node *t = root ;; ){
 71         if( x == t->val ){
 72             splay( t ) ;
 73             return ;
 74         }
 75         t = t->ch[ x > t->val ] ;
 76     }
 77 }
 78 void Splay::change( int x ,int val ){
 79     find( x ) ;
 80     node *p = root ;
 81     node *t = get( root->ch[0]->size ) ;
 82     splay( t ,root ) ;
 83     t->setc( root->ch[1] ,1 ) ;
 84     t->pushup() ,root = t ,t->p = null ;
 85     p->val = val ,p->size = 1 ;
 86     p->ch[0] = p->ch[1] = null ;
 87     insert( p ) ;
 88     return ;
 89 }
 90 node *Splay::get( int s ){
 91     for( node *t = root ;; ){
 92         int k = t->ch[0]->size ;
 93         if( s == k + 1 ) return t ;
 94         if( s > k + 1 ) s -= k + 1 ,t = t->ch[1] ;
 95         else t = t->ch[0] ;
 96     }
 97 }
 98 int Splay::rank( int x ){
 99     int res = 0 ;
100     for( node *t = root ;; ){
101         node *&s = t->ch[ x > t->val ] ;
102         if( t->val < x ) res += t->ch[0]->size + 1 ;
103         if( s == null ){
104             splay(t) ;
105             return res - 1 ;
106         }
107         t = s ;
108     }
109 }
110 void setIt( int p ,int k ,int s = M ,int x = 1 ){
111     tree[x].insert( newnode(k) ) ;
112     if( s == 1 ) return ;
113     if( p <= s/2 ) setIt( p ,k ,s/2 ,x<<1 ) ;
114     else setIt( p - s/2 ,k ,s - s/2 ,x<<1|1 ) ;
115 }
116 void change( int p ,int u ,int v ,int s = M ,int x = 1 ){
117     tree[x].change( u ,v ) ;
118     if( s == 1 ) return ;
119     if( p <= s/2 ) change( p ,u ,v ,s/2 ,x<<1 ) ;
120     else change( p-s/2 ,u ,v ,s-s/2 ,x<<1|1 ) ;
121 }
122 int Q ;
123 void query( int l ,int r ,int ans ,int s = M ,int x = 1 ){
124     if( l <= 1 && r >= s ){
125         Q += tree[x].rank(ans) ;
126         return ;
127     }
128     if( l <= s/2 ) query( l ,r ,ans ,s/2 ,x<<1 ) ;
129     if( r > s/2 ) query( l-s/2 ,r-s/2 ,ans ,s-s/2 ,x<<1|1 ) ;
130 }
131 bool judge( int l ,int r ,int ans ,int kth ){
132     Q = 0 ;
133     query( l ,r ,ans ) ;
134     if( Q <= kth - 1 ) return 1;
135     return 0 ;
136 }
137 void init(){
138     cur = pool ;
139 }
140 void build( int x = 1 ,int s = M ){
141     tree[x].init() ;
142     if( s == 1 ) return ;
143     build( x<<1 ,s/2 ) ;
144     build( x<<1|1 ,s-s/2 ) ;
145 }
146 int main(){
147     int n ,m ,x ,s ,t ,u ;
148     int T ;
149     scanf( "%d" ,&T ) ;
150     while( T -- ){
151         scanf("%d %d" ,&n ,&m ) ;
152         M = n ;
153         init() ;
154         int minn = 0 ,maxn = 0 ;
155         build();
156         for( int i = 1 ;i <= n ;i ++ ){
157             scanf( "%d" ,&x ) ;
158             num[i] = x ;
159             setIt( i ,x ) ;
160             minn = min ( minn ,x ) ;
161             maxn = max ( maxn ,x ) ;
162         }
163         char o[2];
164         while( m -- ){
165             scanf( "%s" ,&o ) ;
166             if( o[0] == 'C' ){
167                 scanf( "%d %d" ,&s ,&t ) ;
168                 minn = min( minn ,t ) ;
169                 maxn = max( maxn ,t ) ;
170                 change( s ,num[s] ,t ) ;
171                 num[s] = t ;
172                 continue ;
173             }
174             scanf( "%d %d %d" ,&s ,&t ,&u ) ;
175             int l = minn ,r = maxn ;
176             while( l < r ){
177                 int mid = ( l + r >> 1 ) + 1 ;
178                 if( judge( s ,t ,mid ,u ) ) l = mid ;
179                 else r = mid - 1 ;
180             }
181             printf( "%d\n" ,l ) ;
182         }
183     }
184 }
CODE

 

转载于:https://www.cnblogs.com/MyWither/p/3563779.html

【使用教程】 一、环境配置 1、建议下载anaconda和pycharm 在anaconda中配置好环境,然后直接导入到pycharm中,在pycharm中运行项目 anaconda和pycharm安装及环境配置参考网上博客,有很多博主介绍 2、在anacodna中安装requirements.txt中的软件包 命令为:pip install -r requirements.txt 或者改成清华源后再执行以上命令,这样安装要快一些 软件包都安装成功后才算成功 3、安装好软件包后,把anaconda中对应的python导入到pycharm中即可(不难,参考网上博客) 二、环境配置好后,开始训练(也可以训练自己数据集) 1、数据集准备 需要准备yolo格式的目标检测数据集,如果不清楚yolo数据集格式,或者有其他数据训练需求,请看博主yolo格式各种数据集集合链接:https://blog.csdn.net/DeepLearning_/article/details/127276492 里面涵盖了上百种yolo数据集,且在不断更新,基本都是实际项目使用。来自于网上收集、实际场景采集制作等,自己使用labelimg标注工具标注的。数据集质量绝对有保证! 本项目所使用的数据集,见csdn该资源下载页面中的介绍栏,里面有对应的下载链接,下载后可直接使用。 2、数据准备好,开始修改配置文件 参考代码中data文件夹下的banana_ripe.yaml,可以自己新建一个不同名称的yaml文件 train:训练集的图片路径 val:验证集的图片路径 names: 0: very-ripe 类别1 1: immature 类别2 2: mid-ripe 类别3 格式按照banana_ripe.yaml照葫芦画瓢就行,不需要过多参考网上的 3、修改train_dual.py中的配置参数,开始训练模型 方式一: 修改点: a.--weights参数,填入'yolov9-s.pt',博主训练的是yolov9-s,根据自己需求可自定义 b.--cfg参数,填入 models/detect/yolov9-c.yaml c.--data参数,填入data/banana_ripe.yaml,可自定义自己的yaml路径 d.--hyp参数,填入hyp.scratch-high.yaml e.--epochs参数,填入100或者200都行,根据自己的数据集可改 f.--batch-size参数,根据自己的电脑性能(显存大小)自定义修改 g.--device参数,一张显卡的话,就填0。没显卡,使用cpu训练,就填cpu h.--close-mosaic参数,填入15 以上修改好,直接pycharm中运行train_dual.py开始训练 方式二: 命令行方式,在pycharm中的终端窗口输入如下命令,可根据自己情况修改参数 官方示例:python train_dual.py --workers 8 --device 0 --batch 16 --data data/coco.yaml --img 640 --cfg models/detect/yolov9-c.yaml --weights '' --name yolov9-c --hyp hyp.scratch-high.yaml --min-items 0 --epochs 500 --close-mosaic 15 训练完会在runs/train文件下生成对应的训练文件及模型,后续测试可以拿来用。 三、测试 1、训练完,测试 修改detect_dual.py中的参数 --weights,改成上面训练得到的best.pt对应的路径 --source,需要测试的数据图片存放的位置,代码中的test_imgs --conf-thres,置信度阈值,自定义修改 --iou-thres,iou阈值,自定义修改 其他默认即可 pycharm中运行detect_dual.py 在runs/detect文件夹下存放检测结果图片或者视频 【备注】 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用!有问题请及时沟通交流。 2、适用人群:计算机相关专业(如计科、信息安全、数据科学与大数据技术、人工智能、通信、物联网、自动化、电子信息等)在校学生、专业老师或者企业员工下载使用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值