【HDU】5314 Happy King【动态树(点分治)】
来源:互联网 发布:淘宝运营报价 编辑:程序博客网 时间:2024/05/17 21:53
传送门:【HDU】5314 Happy King
算法分析:
点分治,子树去重类可做。对于一个重心,取出所有路径按照最大值排序,扫下最小值,插入到线段树里维护个数,双指针扫扫解决。然后对所有重心的儿子对应的子树再做一次去重。这个方法我是今早在床上想了下想到的。
我是动态树,动态树比较裸,对点权排序,然后双指针扫扫,接下来就是链接两棵子树或者拆分两棵子树时的子树的siz。子树siz可以用两个变量维护,一个维护splay树内的子树的siz和,一个维护从这个点连出去的不在splay树上的子树的siz和。然后就做完了。
点分治一般做法复杂度
PS:比赛的时候,没从子树去重类入手,用枚举子树的方法思考怎么都不能去除重复的计数,于是没想到点分治的方法怎么做。而我想到用动态树的瞬间就知道怎么用动态树做了,但是敲到一半的时候竟然傻逼的找了个奇怪的理由否决了= =也是傻逼……导致比赛的时候没做出来……
#include <stdio.h>#include <string.h>#include <bitset>#include <algorithm>using namespace std ;typedef long long LL ;#define clr( a , x ) memset ( a , x , sizeof a )const int MAXN = 100005 ;const int MAXM = 10000005 ;const int MAXE = 200005 ;const int INF = 0x3f3f3f3f ;struct Edge { int v , n ; Edge () {} Edge ( int v , int n ) : v ( v ) , n ( n ) {}} ;struct Point { int x , idx ; bool operator < ( const Point& a ) const { return x < a.x ; }} ;LL ans ;struct Node* null ;struct Node { Node* c[2] ; Node* f ; int siz , outsiz ; int flip ; void newnode () { c[0] = c[1] = f = null ; flip = 0 ; siz = 1 ; outsiz = 0 ; } void reverse () { if ( this == null ) return ; swap ( c[0] , c[1] ) ; flip ^= 1 ; } void up () { if ( this == null ) return ; siz = c[0]->siz + c[1]->siz + c[0]->outsiz + c[1]->outsiz + 1 ; } void down () { if ( this == null ) return ; if ( flip ) { c[0]->reverse () ; c[1]->reverse () ; flip = 0 ; } } bool is_root () { return f == null || f->c[0] != this && f->c[1] != this ; } void setc ( Node* o , int d ) { c[d] = o ; o->f = this ; } void sign_down () { if ( !is_root () ) f->sign_down () ; down () ; } void rot ( int d ) { Node* p = f ; Node* g = p->f ; p->setc ( c[d] , !d ) ; if ( !p->is_root () ) g->setc ( this , f == g->c[1] ) ; else f = g ; setc ( p , d ) ; p->up () ; } Node* splay () { sign_down () ; while ( !is_root () ) { if ( f->is_root () ) rot ( this == f->c[0] ) ; else { if ( f == f->f->c[0] ) { if ( this == f->c[0] ) f->rot ( 1 ) , rot ( 1 ) ; else rot ( 0 ) , rot ( 1 ) ; } else { if ( this == f->c[1] ) f->rot ( 0 ) , rot ( 0 ) ; else rot ( 1 ) , rot ( 0 ) ; } } } up () ; return this ; } Node* access () { Node* o = this ; Node* x = null ; while ( o != null ) { if ( x != null ) { while ( x->c[0] != null ) x = x->c[0] ; x->splay () ; } o->splay () ; o->outsiz += o->c[1]->outsiz + o->c[1]->siz ; o->outsiz -= x->outsiz + x->siz ; o->setc ( x , 1 ) ; o->up () ; x = o ; o = o->f ; } return splay () ; } void make_root () { access ()->reverse () ; splay () ; } void link ( Node* o ) { make_root () ; o->make_root () ; ans += ( LL ) ( siz + outsiz ) * ( o->siz + o->outsiz ) ; o->outsiz += siz + outsiz ; f = o ; } void cut () { access () ; c[0]->f = null ; c[0] = null ; up () ; } void cut ( Node* o ) { make_root () ; o->cut () ; }} ;Node pool[MAXN] ;Node* cur ;Node* node[MAXN] ;Edge E[MAXE] ;int H[MAXN] , cntE ;Point p[MAXN] ;int is[MAXN] ;int n , D ;void clear () { cur = pool ; cur->newnode () ; null = cur ++ ; null->siz = 0 ;}void init () { cntE = 0 ; clr ( is , 0 ) ; clr ( H , -1 ) ;}void addedge ( int u , int v ) { E[cntE] = Edge ( v , H[u] ) ; H[u] = cntE ++ ;}void scanf ( int& x , char c = 0 ) { while ( ( c = getchar () ) < '0' ) ; x = c - '0' ; while ( ( c = getchar () ) >= '0' ) x = x * 10 + c - '0' ;}void solve () { int u , v ; init () ; clear () ; scanf ( n ) ; scanf ( D ) ; for ( int i = 1 ; i <= n ; ++ i ) { scanf ( p[i].x ) ; p[i].idx = i ; cur->newnode () ; node[i] = cur ++ ; } sort ( p + 1 , p + n + 1 ) ; for ( int i = 1 ; i < n ; ++ i ) { scanf ( u ) ; scanf ( v ) ; addedge ( u , v ) ; addedge ( v , u ) ; } int l = 1 ; ans = 0 ; for ( int i = 1 ; i <= n ; ++ i ) { while ( l <= i && p[i].x - p[l].x > D ) { int u = p[l].idx ; for ( int j = H[u] ; ~j ; j = E[j].n ) { int v = E[j].v ; if ( !is[v] ) continue ; node[u]->cut ( node[v] ) ; } is[u] = 0 ; ++ l ; } int u = p[i].idx ; for ( int j = H[u] ; ~j ; j = E[j].n ) { int v = E[j].v ; if ( !is[v] ) continue ; node[u]->link ( node[v] ) ; } is[u] = 1 ; } printf ( "%lld\n" , ans * 2 ) ;}int main () { int T ; scanf ( T ) ; for ( int i = 1 ; i <= T ; ++ i ) { solve () ; } return 0 ;}
0 0
- 【HDU】5314 Happy King【动态树(点分治)】
- HDU 5314 Happy King 点分治
- 【树分治】 HDOJ 5314 Happy King
- hdu-5314 Happy King
- hdu 5314 Happy King 树点分冶 树状数组
- hdu 5571 tree (动态点分治)
- hdu 4918 Query on the subtree (动态点分治+动态开点+线段树)
- hdu-4812(树分治 点权)
- 【HDU】5571 tree【动态点分治】
- 树分治(点分治+边分治)
- Hdu 5314 Happy King(求树上多少个点对(u,v)满足u到v的路径上点权值最大值减最小值不大于给定的K)
- 【HDU】5267 pog loves szh IV【动态点分治】
- bzoj 3730: 震波 (动态点分治)
- BZOJ4012【动态点分治】
- HDU 4812 D Tree (树分治之点分治)
- 树分治-点分治
- hdu 4918 点分治
- 【hdu 4812】点分治
- angular的指令的子作用域继承问题
- 捕获键盘的每个字符,包括不可打印字符
- HDU 5290 Bombing plan 树形dp
- C++构造函数与传默认值的关系
- 三维建模贴图技巧
- 【HDU】5314 Happy King【动态树(点分治)】
- 【试水CAS-4.0.3】第08节_CAS客户端配置单点登出
- Android开发学习笔记十五 webservice工具类
- AfxMessageBox和MessageBox区别
- 当前页面需要显示上传的图片。图片并不需要上传到服务器存入数据库中
- FZU 2157 树形DP
- Tortoisesvn介绍
- nyoj117 求逆序数【线段树】
- 揭秘家用路由器0day漏洞挖掘技术——互动出版网