【openjudge】C15C Rabbit's Festival【CDQ分治+并查集】 缺乏、安全感 2022-08-05 00:56 120阅读 0赞 传送门:[【openjudge】C15C Rabbit’s Festival][openjudge_C15C Rabbit_s Festival] 题目分析: 考虑到每条边最多只断一天,我们可以用cdq来模拟这个过程。假设当前区间为\[l,r\],令m=(l\+r)/2,选择\[l,m\]区间时,我们便将\[m\+1,r\]内的边全部使用掉,然后递归处理\[l,m\]部分。处理完\[l,m\]部分后我们将\[m\+1,r\]回溯掉,然后将\[l,m\]内的边都使用掉,递归处理\[m\+1,r\]部分,最后再将\[l,m\]内使用的边回溯掉…… YY一下,我们可以发现这个过程正好模拟了并查集的加边过程(利用了逐层并差集的方法)。 最后我们发现每个区间我们恰好用了一次,一共log ( K )层,所以一共我们使用了O ( K log ( K ) )个元素,接下来我们考虑里面的并查集,为了保证并查集的复杂度,我们考虑启发式合并,高度小的合并到高度大的上面。这里我们假设是一个 log ,那么算法总复杂度为O ( K log2 ( K ) )。 #include <stdio.h> #include <string.h> #include <algorithm> using namespace std ; typedef long long LL ; #define clr( a , x ) memset ( a , x , sizeof a ) #define cpy( a , x ) memcpy ( a , x , sizeof a ) const int MAXN = 100005 ; const int MAXE = 200005 ; struct Edge { int u , v , n ; Edge () {} Edge ( int u , int v , int n ) : u ( u ) , v ( v ) , n ( n ) {} } ; struct Node { int u , v , cntu , cntv , ranku , rankv ; Node () {} Node ( int u , int v , int cntu , int cntv , int ranku , int rankv ) : u ( u ) , v ( v ) , cntu ( cntu ) , cntv ( cntv ) , ranku ( ranku ) , rankv ( rankv ) {} } ; Edge E[MAXE] ; int H[MAXN] , cntE ; int n , m , k ; Node S[MAXE] ; int cnt[MAXN] ; int p[MAXN] ; int rank[MAXN] ; int top ; LL ans ; void init () { ans = 0 ; top = 0 ; cntE = 0 ; clr ( H , -1 ) ; } void addedge ( int x , int u , int v ) { E[cntE] = Edge ( u , v , H[x] ) ; H[x] = cntE ++ ; } int find ( int x ) { int o = x ; while ( p[o] != o ) o = p[o] ; int ans = o ; while ( p[x] != x ) { int tmp = p[x] ; p[x] = tmp ; x = tmp ; } return ans ; } void Union ( int l , int r ) { for ( int t = l ; t <= r ; ++ t ) { for ( int i = H[t] ; ~i ; i = E[i].n ) { int u = find ( E[i].u ) ; int v = find ( E[i].v ) ; if ( u == v ) continue ; S[top ++] = Node ( u , v , cnt[u] , cnt[v] , rank[u] , rank[v] ) ; ans += ( LL ) cnt[u] * cnt[v] ; if ( rank[u] <= rank[v] ) { rank[v] = max ( rank[v] , rank[u] + 1 ) ; p[u] = v ; cnt[v] += cnt[u] ; } else { p[v] = u ; cnt[u] += cnt[v] ; } } } } void back ( int x ) { while ( top > x ) { -- top ; int u = S[top].u , v = S[top].v ; ans -= ( LL ) S[top].cntu * S[top].cntv ; p[u] = u ; p[v] = v ; cnt[u] = S[top].cntu ; cnt[v] = S[top].cntv ; rank[u] = S[top].ranku ; rank[v] = S[top].rankv ; } } void cdq ( int l , int r ) { if ( l == r ) { printf ( "%lld\n" , ans ) ; return ; } int m = ( l + r ) >> 1 ; int rtop = top ; Union ( m + 1 , r ) ; cdq ( l , m ) ; back ( rtop ) ; Union ( l , m ) ; cdq ( m + 1 , r ) ; back ( rtop ) ; } void solve () { int u , v , c ; init () ; for ( int i = 1 ; i <= n ; ++ i ) { p[i] = i ; cnt[i] = 1 ; rank[i] = 0 ; } for ( int i = 0 ; i < m ; ++ i ) { scanf ( "%d%d%d" , &u , &v , &c ) ; if ( c > k ) { u = find ( u ) ; v = find ( v ) ; if ( u == v ) continue ; if ( rank[u] <= rank[v] ) { rank[v] = max ( rank[v] , rank[u] + 1 ) ; p[u] = v ; cnt[v] += cnt[u] ; } else { p[v] = u ; cnt[u] += cnt[v] ; } } else addedge ( c , u , v ) ; } cdq ( 1 , k ) ; } int main () { while ( ~scanf ( "%d%d%d" , &n , &m , &k ) ) solve () ; return 0 ; } [openjudge_C15C Rabbit_s Festival]: http://poj.openjudge.cn/practice/C15C/
相关 【openjudge】C15C Rabbit's Festival【CDQ分治+并查集】 传送门:[【openjudge】C15C Rabbit’s Festival][openjudge_C15C Rabbit_s Festival] 题目分析: 考虑到每条边 缺乏、安全感/ 2022年08月05日 00:56/ 0 赞/ 121 阅读
相关 并查集 Ⅱ \[poj 1611\] ([http://poj.org/problem?id=1611][http_poj.org_problem_id_1611]) 题目描述: T 古城微笑少年丶/ 2022年08月03日 14:35/ 0 赞/ 258 阅读
相关 并查集 并查集JAVA版框架 并查集是一种用来管理元素分组情况的数据结构。 并查集可以高效地进行如下操作: \--查询元素a和元素b是否属于同一组 落日映苍穹つ/ 2022年06月16日 12:44/ 0 赞/ 295 阅读
相关 并查集 这个文章是几年前水acm的时候转的, 当时也不知道作者是谁, 要是有人知道的话说一下吧 并查集是我暑假从高手那里学到的一招,觉得真是太精妙的设计了。以前我无法解决的 港控/mmm°/ 2022年06月13日 14:13/ 0 赞/ 279 阅读
相关 并查集 > 题目 > 某学校近期要组织全校同学出去参加某项活动,由于人数众多,学校决定让同学们自行组队,以小组为单位进行活动。假设学校一共n个同学,每个同学有一个唯一的数字作为标签 Myth丶恋晨/ 2022年06月08日 09:24/ 0 赞/ 293 阅读
相关 并查集 森林: 森林是由若干棵互不相交的树组成,两棵树分别独立,没有交集 ![20181112082744488.png][] 并查集: 并查集的结构和森林十分相似,是 Love The Way You Lie/ 2022年04月17日 02:27/ 0 赞/ 348 阅读
相关 并查集 来看一个实例,[杭电1232畅通工程][1232] 首先在地图上给你若干个城镇,这些城镇都可以看作点,然后告诉你哪些对城镇之间是有道路直接相连的。最后要解决的是整幅图的连通性 我就是我/ 2022年03月29日 10:58/ 0 赞/ 346 阅读
相关 并查集 例题: ![输入样例][20190805122001677.png] 输入样例,第一行为一个整数n,代表有n台电脑,编号1-n;接下来进行一系列操作,当输入‘c’时,判 Dear 丶/ 2021年11月11日 08:04/ 0 赞/ 373 阅读
相关 并查集 一、算法解释 用于解决一些有N个元素的集合应用问题。 1、将每个元素初始化为自身单独成为一个集合。用p\[i\]的值表示该元素所在集合。 ![这里写图片描述][S 桃扇骨/ 2021年09月14日 02:56/ 0 赞/ 452 阅读
相关 并查集 并查集的作用就是快速判断两个元素是否在同一个集合中,快速将两个集合合并 基本模板 include <iostream> include <a 比眉伴天荒/ 2021年06月22日 15:37/ 0 赞/ 544 阅读
还没有评论,来说两句吧...