传送门:【HDU】5267 pog loves szh IV

题目分析:首先我们用树分治,对每一个分治重心,以此为根的子树,建立一棵线段树。可以发现总节点数只有$O(NlogN)$,因为每一层都是$N$个节点,且只有$logN$层。然后,还有一个特点就是,一个点最多属于$logN$个中心,这样我们查询和更新,就是在$logN$重心树中用$logN$的复杂度更新线段树的区间。线段树的每个叶节点表示这个节点到该重心树的树根的异或值。然后接下来就不难了,仔细想想基本都可以理论AC了……当然做起来可能不是那么轻松……对于这个题目分析我就说道这好了。

PS:这是我写过最长的代码,加上调试信息,都快要10000B了……OWO

13935644 2015-06-29 17:56:10 Accepted 5267 2480MS 13940K 9648 B G++ poursoul

my code:

#include <bits/stdc++.h>
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 )
#define ls T[o].Ls
#define rs T[o].Rs
#define lson rs , T[o].l , m
#define rson ls , m + 1 , T[o].r
#define mid ( ( T[o].l + T[o].r ) >> 1 )const int MAXN = 10005 ;
const int MAXE = 20005 ;struct Edge {int v , n ;Edge () {}Edge ( int v , int n ) : v ( v ) , n ( n ) {}
} ;struct Node {int L , R , tree , subtree ;Node () {}Node ( int L , int R , int t , int t2 = 0 ) : L ( L ) , R ( R ) , tree ( t ) , subtree ( t2 ) {}
} ;
struct Tree {int l , r , Ls , Rs , sum , lazy ;
} ;Edge E[MAXE] ;
int H[MAXN] , cntE ;
int vis[MAXN] , siz[MAXN] , pre[MAXN] ;
int Q[MAXN] , head , tail ;
int in[MAXN * 15] , ou[MAXN * 15] , dfs_clock ;
pair < int , int > op[MAXN] ;
//pair < pair < int , int > , int > Root[MAXN * 2] ;
vector < Node > G[MAXN] ;
Node node[MAXN] , Root[MAXN * 2] ;
int cnt ;int n , m ;
int val[MAXN] ;
LL ans[MAXN] , res ;
int zero[MAXN * 2] , one[MAXN * 2] ;
Tree T[MAXN * 60] ;
int Troot[MAXN * 2] , cur ;
int tot[MAXN * 2] , tmp[MAXN * 2] ;void init () {cnt = 0 ;cntE = 0 ;dfs_clock = 0 ;clr ( tot , 0 ) ;clr ( vis , 0 ) ;clr ( ans , 0 ) ;clr ( H , -1 ) ;
}void addedge ( int u , int v ) {E[cntE] = Edge ( v , H[u] ) ;H[u] = cntE ++ ;
}int get_root ( int s ) {head = tail = 0 ;pre[s] = 0 ;Q[tail ++] = s ;while ( head != tail ) {int u = Q[head ++] ;for ( int i = H[u] ; ~i ; i = E[i].n ) {int v = E[i].v ;if ( vis[v] || v == pre[u] ) continue ;pre[v] = u ;Q[tail ++] = v ;}}int root = s , root_siz = n ;while ( head ) {int u = Q[-- head] , cnt = 0 ;siz[u] = 1 ;for ( int i = H[u] ; ~i ; i = E[i].n ) {int v = E[i].v ;if ( vis[v] || v == pre[u] ) continue ;siz[u] += siz[v] ;if ( cnt < siz[v] ) cnt = siz[v] ;}cnt = max ( cnt , tail - siz[u] ) ;if ( cnt < root_siz ) {root_siz = cnt ;root = u ;}}return root ;
}void get_tree ( int u , int f , int tree , int subtree ) {in[u] = ++ dfs_clock ;for ( int i = H[u] ; ~i ; i = E[i].n ) {int v = E[i].v ;if ( vis[v] || v == f ) continue ;get_tree ( v , u , tree , subtree ) ;}ou[u] = dfs_clock ;G[u].push_back ( Node ( in[u] , ou[u] , tree , subtree ) ) ;
}void dfs ( int u ) {int root = get_root ( u ) ;vis[root] = 1 ;int tree = ++ cnt ;in[root] = ++ dfs_clock ;for ( int i = H[root] ; ~i ; i = E[i].n ) {int v = E[i].v ;if ( vis[v] ) continue ;int subtree = ++ cnt ;get_tree ( v , 0 , tree , subtree ) ;//Root[subtree] = make_pair ( make_pair ( in[v] , ou[v] ) , tree ) ;Root[subtree] = Node ( in[v] , ou[v] , tree ) ;tot[tree] -= ( ou[v] - in[v] ) * ( ou[v] - in[v] + 1 ) ;}ou[root] = dfs_clock ;tot[tree] += ( ou[root] - in[root] ) * ( ou[root] - in[root] + 1 ) ;//Root[tree] = make_pair ( make_pair ( in[root] , ou[root] ) , 0 ) ;Root[tree] = Node ( in[root] , ou[root] , tree ) ;node[root] = Node ( in[root] , ou[root] , tree ) ;for ( int i = H[root] ; ~i ; i = E[i].n ) {int v = E[i].v ;if ( !vis[v] ) dfs ( v ) ;}
}void pushdown ( int o ) {int m = mid ;if ( T[o].lazy ) {T[ls].lazy ^= 1 ;T[rs].lazy ^= 1 ;T[ls].sum = m - T[o].l + 1 - T[ls].sum ;T[rs].sum = T[o].r - m - T[rs].sum ;T[o].lazy = 0 ;}
}void build ( int& o , int l , int r ) {o = ++ cur ;T[o].l = l ;T[o].r = r ;T[o].sum = T[o].lazy = 0 ;if ( l == r ) return ;int m = mid ;build ( T[o].Ls , l , m ) ;build ( T[o].Rs , m + 1 , r ) ;
}void update ( int L , int R , int o ) {if ( L <= T[o].l && T[o].r <= R ) {T[o].lazy ^= 1 ;T[o].sum = T[o].r - T[o].l + 1 - T[o].sum ;return ;}pushdown ( o ) ;int m = mid ;if ( L <= m ) update ( L , R , ls ) ;if ( m <  R ) update ( L , R , rs ) ;T[o].sum = T[ls].sum + T[rs].sum ;
}int query ( int L , int R , int o ) {if ( L <= T[o].l && T[o].r <= R ) return T[o].sum ;pushdown ( o ) ;int m = mid ;if ( R <= m ) return query ( L , R , ls ) ;if ( m <  L ) return query ( L , R , rs ) ;return query ( L , R , ls ) + query ( L , R , rs ) ;
}void show ( int o ) {if ( T[o].l == T[o].r ) {if ( T[o].l <= 5 ) printf ( "%d " , T[o].sum ) ;if ( T[o].l == 5 ) printf ( "\n" ) ;return ;}pushdown ( o ) ;int m = mid ;show ( ls ) ;show ( rs ) ;
}void solve () {int u , v ;init () ;for ( int i = 1 ; i <= n ; ++ i ) {scanf ( "%d" , &val[i] ) ;G[i].clear () ;}for ( int i = 1 ; i < n ; ++ i ) {scanf ( "%d%d" , &u , &v ) ;addedge ( u , v ) ;addedge ( v , u ) ;}dfs ( 1 ) ;for ( int i = 1 ; i <= m ; ++ i ) {scanf ( "%d%d" , &op[i].first , &op[i].second ) ;}/*for ( int j = 1 ; j <= n ; ++ j ) {printf ( "%d %d\n" , node[j].first , node[j].second ) ;}*/for ( int i = 0 ; i < 15 ; ++ i ) {cur = 0 ;clr ( tmp , 0 ) ;for ( int j = 1 ; j <= n ; ++ j ) {build ( Troot[node[j].tree] , node[j].L , node[j].R ) ;}for ( int j = 1 ; j <= n ; ++ j ) if ( val[j] & 1 ) {//printf ( "%d %d\n" , node[j].first , node[j].second , dfs_clock ) ;update ( node[j].L , node[j].R , Troot[node[j].tree] ) ;for ( int k = 0 ; k < G[j].size () ; ++ k ) {int L = G[j][k].L ;int R = G[j][k].R ;int tree = G[j][k].tree ;//if ( i == 0 ) printf ( "%d %d %d %d\n" , L , R , T[Troot[tree]].l , T[Troot[tree]].r ) ;update ( L , R , Troot[tree] ) ;}}res = 0 ;for ( int j = 1 ; j <= cnt ; ++ j ) {int tree = Root[j].tree ;int L = Root[j].L ;int R = Root[j].R ;int L1 = Root[tree].L ;int R1 = Root[tree].R ;//if ( !i ) printf ( "%d %d %d %d %d %d\n" , L , R , L1 , R1 , j , tree ) ;one[j] = query ( L , R , Troot[tree] ) ;//printf ( "ok\n" ) ;zero[j] = R - L + 1 - one[j] ;//if ( i == 0 ) printf ( "%d %d %d %d\n" , L , R , zero[j] , one[j] ) ;}for ( int j = 1 ; j <= cnt ; ++ j ) {if ( Root[j].tree != j ) {int tree = Root[j].tree ;int L = Root[tree].L ;int color = query ( L , L , Troot[tree] ) ;int x1 = zero[tree] - zero[j] ;int y1 = one[tree] - one[j] ;int x2 = zero[j] ;int y2 = one[j] ;//if ( i == 0 ) printf ( "%d %d %d %d\n" , x1 , x2 , y1 , y2 ) ;//if ( !i ) printf ( "%d %d %d %d\n" , x1 , x2 , y1 , y2 ) ;//if ( !i ) printf ( "1.%lld " , res ) ;int t ;if ( color ) t = x1 * x2 + y1 * y2 ;else t = x1 * y2 + x2 * y1 ;tmp[tree] += t ;res += t ;//if ( !i ) printf ( "%lld\n" , res ) ;} else {int tree = Root[j].tree ;int L = Root[tree].L ;int color = query ( L , L , Troot[tree] ) ;//if ( !i ) printf ( "0.%lld " , res ) ;res += one[j] - color ;tmp[tree] += one[j] - color ;//if ( !i ) printf ( "%lld\n" , res ) ;}}//if ( i < 3 ) printf ( "%lld\n" , res ) ;ans[0] += res * ( 1 << i ) ;for ( int j = 1 ; j <= m ; ++ j ) {int x = op[j].first ;if ( ( val[x] & 1 ) != ( op[j].second & 1 ) ) {for ( int k = 0 ; k < G[x].size () ; ++ k ) {int L = G[x][k].L ;int R = G[x][k].R ;int tree = G[x][k].tree ;int subtree = G[x][k].subtree ;int color = query ( Root[tree].L , Root[tree].L , Troot[tree] ) ;int t ;if ( i == 0 && j == 4 ) {//printf ( "mid:%d %d %d %d\n" , color , op[j].second & 1 , tree , subtree ) ;}one[subtree] = query ( Root[subtree].L , Root[subtree].R , Troot[tree] ) ;zero[subtree] = Root[subtree].R - Root[subtree].L + 1 - one[subtree] ;if ( i == 0 && j == 4 ) {//printf ( "next:%lld %d %d %d %d %d %d\n" , res , tmp[tree] , zero[subtree] , one[subtree] , zero[tree] , one[tree] , t ) ;}zero[tree] -= zero[subtree] ;one[tree] -= one[subtree] ;if ( color ) t = zero[tree] * zero[subtree] + one[tree] * one[subtree] ;else t = zero[tree] * one[subtree] + zero[subtree] * one[tree] ;res -= 2 * t ;tmp[tree] -= 2 * t ;if ( i == 0 && j == 4 ) {//printf ( "next:%lld %d %d %d %d %d %d\n" , res , tmp[tree] , zero[subtree] , one[subtree] , zero[tree] , one[tree] , t ) ;}update ( L , R , Troot[tree] ) ;one[subtree] = query ( Root[subtree].L , Root[subtree].R , Troot[tree] ) ;zero[subtree] = Root[subtree].R - Root[subtree].L + 1 - one[subtree] ;if ( color ) t = zero[tree] * zero[subtree] + one[tree] * one[subtree] ;else t = zero[tree] * one[subtree] + zero[subtree] * one[tree] ;res += 2 * t ;tmp[tree] += 2 * t ;zero[tree] += zero[subtree] ;one[tree] += one[subtree] ;}int L = node[x].L ;int R = node[x].R ;int tree = node[x].tree ;int color = query ( L , L , Troot[tree] ) ;//if ( i == 0 && j == 1 ) printf ( "%d %d %lld\n" , color , op[j].second & 1 , res ) ;swap ( zero[tree] , one[tree] ) ;update ( L , R , Troot[tree] ) ;res -= tmp[tree] ;tmp[tree] = tot[tree] - tmp[tree] ;res += tmp[tree] ;val[x] ^= 1 ;}ans[j] += res * ( 1 << i ) ;}for ( int j = 1 ; j <= n ; ++ j ) {val[j] >>= 1 ;}for ( int j = 1 ; j <= m ; ++ j ) {op[j].second >>= 1 ;}}for ( int i = 1 ; i <= m ; ++ i ) {printf ( "%I64d\n" , ans[i] ) ;}
}int main () {while ( ~scanf ( "%d%d" , &n , &m ) ) solve () ;return 0 ;
}

【HDU】5267 pog loves szh IV【动态点分治】相关推荐

  1. hdu 5265 pog loves szh II STL

    pog loves szh II Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://acm.hdu.edu.cn/showproblem.php? ...

  2. hdu 5265 pog loves szh II

    题目连接 http://acm.hdu.edu.cn/showproblem.php?pid=5265 pog loves szh II Description Pog and Szh are pla ...

  3. hdu 5264 pog loves szh I

    题目连接 http://acm.hdu.edu.cn/showproblem.php?pid=5264 pog loves szh I Description Pog has lots of stri ...

  4. HDU 5266 pog loves szh III【LCA RMQ】

    B - pog loves szh III 题目:添加链接描述 题意:找出区域l到r的LCA->找l和r的LCA 分析: 链式前向星存树,先用dfs处理结点倍增关系. 然后从循环处理较深结点,直 ...

  5. HDU 5266 pog loves szh III (LAC)

    问题描述 pog在与szh玩游戏,首先pog在纸上画了一棵有根树,这里我们定义1为这棵树的根,然后szh在这棵树中选了若干个点,想让pog帮忙找找这些点的最近公共祖先在哪里,一个点为S的最近公共祖先当 ...

  6. HDU - 5265 pog loves szh II (二分或者贪心)

    这题有两种做法,一种是二分,我很快就想到了(nlogn的复杂度,10^6的n). 第二种就是贪心了,我觉得这个不那么容易想到,好像速度要快一些. 首先,我们找答案的两个数x,y,有两种,一种是x+y& ...

  7. hdu 5266 pog loves szh III

    给一棵树,q次询问,每次询问给连续的一个闭区间,问区间所有数的LCA是多少. 做一个dfs序,其中把dfs序最小的点和最大的点做一次LCA求出的点就是答案. #include <bits/std ...

  8. hdu 5266 pog loves szh III LCA+RMQ

    题意: 给你一棵树,然后询问l~r节点的最近公共祖先(LCA). 思路: 用RMQ维护一段区间的LCA,然后询问时,将两个区间的LCA再求一次LCA即可. code: #pragma comment( ...

  9. HDU 5266 pog loves szh III(在线倍增LCA+ST)

    Description 给出一棵有n个节点的树,定义1为树根,有q次询问,每次询问区间[a,b]中所有节点的LCA Input 第一行为一整数n表示节点数,之后n-1行每行两个整数a和b表示树的一条边 ...

最新文章

  1. 阿里、腾讯、美团、小米……各公司月饼大PK,看完简直想哭泣!
  2. 关于ORA-06508 , ORA-04068异常的详细说明
  3. 适合自学python的图书-有哪些适合零编程基础的人学习Python的书?
  4. UA MATH563 概率论的数学基础 中心极限定理11 强大数定律 版本1:四阶矩有界
  5. 舰r4月28服务器维护,崩坏3 11月28日版本更新维护通知
  6. 看完师兄的代码笔记,我失眠了
  7. mysql 表列表_一个MySQL表中的多列表显示
  8. IDEA连接Git后类的颜色含义
  9. 【渝粤教育】电大中专学习指南 (2)作业 题库
  10. Java程序怎么运行?
  11. Java 技术体系简介
  12. 51nod1127 最短的包含字符串
  13. ubuntu16.10+cuda8.0+cudnn+caffe+opencv3.2+anaconda2
  14. 1548 A Simple Problem with Integers
  15. 未来计算机手抄报图片,【科技与未来手抄报图片大全】未来科技手抄报图片_科技创造未来手抄报设计_亲亲宝贝网...
  16. 揭秘郭盛华的真实收入,事实和你想的真不一样
  17. Linux内核下载(包括历史版本)
  18. 仿网易云音乐部分UI实现
  19. Django:将项目移动到新环境
  20. AtCoder Beginner Contest 203 Pond(二分+二维前缀和)

热门文章

  1. pip._vendor.urllib3.exceptions.ReadTimeoutError: HTTPSConnectionPool(host=files.pythonhosted.org解决方案
  2. 计算机软件资格水平考试办公室,信息系统项目管理师考试大纲-全国计算机技术与软件专业技术资格(水平)考试办公室.pdf...
  3. 14. 编写递归函数,在第一行打印输出1个1,在第二行输出2个2,。。。,在第n行输出n个n。
  4. 《数字电子技术基础》读书笔记:存储器
  5. 堡垒机动态口令使用手册
  6. “服务不可用“怎么排查?
  7. python谷歌地图查找附近地铁站_如何在谷歌地图中可视化显示路线
  8. Nginx启动问题解决
  9. 男孩子学机电一体化好还是计算机好,男生学机电一体化专业好吗 好找工作吗...
  10. slimscroll Unable to preventDefault inside passive event listener due to target being treated as pas