"BestCoder"杯中国大学生程序设计冠军赛 HDU 5221 Occupation
来源:互联网 发布:人工智能前沿技术 编辑:程序博客网 时间:2024/06/05 18:24
题目链接~~>
做题感悟 :区域赛过后就没写过树剖 ,只记得思想,比赛时想到了,但是只打代码就打了半个多小时(真是醉了!!),然后就是不断的调试代码,悲催的是调了一个多小时也没调出来。。。。。
解题思路:这题只要想到某个节点的子树的所有节点编号都大于此节点的编号(在线段树中的位置的编号,树剖的时候编号都是连续的)且是连续的,那么我们只要深搜的时候记录一下子树最大的一个子节点的时间戳(在线段树中的编号),只要我们利用一个节点的进去的时间戳和出去的时间戳就可以对这个节点的子树操作了(CF上有一个处理子树类似的题),其它的两个操作就 so easy 了,线段树写的很挫,请见谅。。。
代码:
#pragma comment(linker, "/STACK:102400000,102400000")#include <iostream>#include <string.h>#include <math.h>#include <queue>#include <algorithm>#include <stdlib.h>#include <map>#include <set>#include <stdio.h>#include <vector>#define L(x) (x*2)#define R(x) (x*2 + 1)using namespace std;const int INF = 0x3f3f3f3f ;const int MX = 100000 + 5 ;int n ,m ,num ,idx ,sum ;int dep[MX] ,top[MX] ,V[MX] ,ti[MX] ,to[MX] ,head[MX] ,father[MX] ,siz[MX] ,son[MX] ;struct Edge{ int v ,next ;}E[MX*2] ;void add_edge(int u ,int v){ E[num].v = v ; E[num].next = head[u] ; head[u] = num++ ; E[num].v = u ; E[num].next = head[v] ; head[v] = num++ ;}void dfs_find(int u ,int fa){ dep[u] = dep[fa] + 1 ; father[u] = fa ; siz[u] = 1 ; son[u] = 0 ; for(int i = head[u] ;i != -1 ; i = E[i].next) { int v = E[i].v ; if(v == fa) continue ; dfs_find(v ,u) ; siz[u] += siz[v] ; if(siz[son[u]] < siz[v]) son[u] = v ; }}void dfs_time(int u ,int fa){ ti[u] = idx++ ; top[u] = fa ; if(son[u]) dfs_time(son[u] ,top[u]) ; for(int i = head[u] ;i != -1 ;i = E[i].next) { int v = E[i].v ; if(v == father[u] || v == son[u]) continue ; dfs_time(v ,v) ; } to[u] = idx-1 ;}void init(){ sum = 0 ; num = 0 ; memset(head ,-1 ,sizeof(head)) ;}//线段树 ---------------------struct node{ int le ,rt ,sum ,flag ;}T[MX*4] ;void build(int x ,int le ,int rt){ T[x].sum = 0 ; T[x].flag = true ; T[x].le = le ; T[x].rt = rt ; if(le == rt) return ; int Mid = (le + rt)>>1 ; build(L(x) ,le ,Mid) ; build(R(x),Mid+1 ,rt) ;}void push_up(int x){ T[x].sum = T[L(x)].sum + T[R(x)].sum ; T[x].flag = true ;}void push_down(int x){ if(!T[x].flag) { T[L(x)].sum = T[R(x)].sum = 0 ; T[L(x)].flag = T[R(x)].flag = false ; T[x].sum = 0 ; }}bool Findpos(int x ,int pos){ if(T[x].le == T[x].rt && T[x].le == pos) { if(!T[x].flag) T[x].sum = 0 ; return T[x].flag ; } push_down(x) ; int Mid = (T[x].le + T[x].rt)>>1 ; if(pos <= Mid) return Findpos(L(x) ,pos) ; else return Findpos(R(x) ,pos) ; push_up(x) ;}void insert(int x ,int pos ,int w) // 修改点{ if(T[x].le == T[x].rt && T[x].le == pos) { T[x].sum = w ; T[x].flag = true ; return ; } push_down(x) ; int Mid = (T[x].le + T[x].rt)>>1 ; if(pos <= Mid) insert(L(x) ,pos ,w) ; else insert(R(x) ,pos ,w) ; push_up(x) ;}void update(int x ,int Le ,int Rt) // 区间清零{ if(T[x].le == Le && T[x].rt == Rt) { T[x].flag = false ; T[x].sum = 0 ; return ; } push_down(x) ; int Mid = (T[x].le + T[x].rt)>>1 ; if(Le > Mid) update(R(x) ,Le ,Rt) ; else if(Rt <= Mid) update(L(x) ,Le ,Rt) ; else { update(L(x) ,Le ,Mid) ; update(R(x) ,Mid+1 ,Rt) ; } push_up(x) ;}int Query(int x ,int Le ,int Rt) // 区间求和{ if(T[x].le == Le && T[x].rt == Rt) { if(!T[x].flag) T[x].sum = 0 ; int temp = T[x].sum ; T[x].sum = 0 ; T[x].flag = false ; return temp ; } push_down(x) ; int Mid = (T[x].le + T[x].rt)>>1 ; if(Le > Mid) return Query(R(x) ,Le ,Rt) ; else if(Rt <= Mid) return Query(L(x) ,Le ,Rt) ; else return Query(L(x) ,Le ,Mid) + Query(R(x) ,Mid+1 ,Rt) ;}void LCA(int u ,int v){ int temp ; while(top[u] != top[v]) { if(dep[top[u]] < dep[top[v]]) swap(u ,v) ; temp = Query(1 ,ti[top[u]] ,ti[u]) ; update(1 ,ti[top[u]] ,ti[u]) ; sum += temp ; u = father[top[u]] ; } if(dep[u] > dep[v]) swap(u ,v) ; temp = Query(1 ,ti[u] ,ti[v]) ; update(1 ,ti[u] ,ti[v]) ; sum += temp ;}int main(){ //freopen("input.txt" ,"r" ,stdin) ; int Tx ,u ,v ; scanf("%d" ,&Tx) ; while(Tx--) { init() ; scanf("%d" ,&n) ; for(int i = 1 ;i <= n ; ++i) scanf("%d" ,&V[i]) ; for(int i = 1 ;i < n ; ++i) { scanf("%d%d" ,&u ,&v) ; add_edge(u ,v) ; } dep[1] = siz[0] = 0 ; dfs_find(1 ,1) ; idx = 1 ; dfs_time(1 ,1) ; build(1 ,1 ,n) ; for(int i = 1 ;i <= n ; ++i) insert(1 ,ti[i] ,V[i]) ; scanf("%d" ,&m) ; int type ; for(int i = 0 ;i < m ; ++i) { scanf("%d%d" ,&type ,&u) ; if(type == 1) { scanf("%d" ,&v) ; LCA(u ,v) ; } else if(type == 2) { bool flag = Findpos(1 ,ti[u]) ; if(!flag) // 如果为 false 说明已经被占据 { insert(1 ,ti[u] ,V[u]) ; sum -= V[u] ; } } else if(type == 3) { sum += Query(1 ,ti[u] ,to[u]) ; update(1 ,ti[u] ,to[u]) ; } cout<<sum<<endl ; } } return 0 ;}
0 0
- "BestCoder"杯中国大学生程序设计冠军赛 HDU 5221 Occupation
- 赛码"BestCoder"杯中国大学生程序设计冠军赛
- 赛码"BestCoder"杯中国大学生程序设计冠军赛hdu5216
- 赛码"BestCoder"杯中国大学生程序设计冠军赛
- HDU 5214 Movie (赛码"BestCoder"杯中国大学生程序设计冠军赛A题)
- 赛码"BestCoder"杯中国大学生程序设计冠军赛1008(hdu5221)树链剖分点权
- 【HDU】5221 Occupation【树链剖分】
- hdu 5221 Occupation
- HDU 5221 Occupation
- Hdu 5221 Occupation
- hdu 5221 Occupation(树链剖分)
- HDU 5221 Occupation dfs序版树链剖分
- HDU 5221 Occupation(树链剖分)
- HDU 5221 Occupation(树链剖分)
- 【HDU 5221】 Occupation 【树链剖分+线段树】
- hdu 5221 Occupation (树剖+线段树)
- HDU "巴卡斯杯" 中国大学生程序设计竞赛 - 女生专场 Combine String
- "巴卡斯杯" 中国大学生程序设计竞赛 - 女生专场(重现) HDU 5702
- JVM的GC机制<一>新生代GC
- 谈谈我对攻读计算机研究生的看法
- CUDA存储器模型
- hdu3783&&九度1032 ZOJ(字符串或栈)
- java全排列算法实现 --- 小例子实现
- "BestCoder"杯中国大学生程序设计冠军赛 HDU 5221 Occupation
- BZOJ 4029: [HEOI2015]定价
- c#调用DLL
- nginx+php+mysql服务器搭建
- 循环单链表的基本操作
- 微商如何购买微信小号推广?
- 两个链表的第一个公共结点
- LeetCode | Minimum Path Sum
- MySQL部分解疑