"BestCoder"杯中国大学生程序设计冠军赛 HDU 5221 Occupation
【摘要】 题目链接~~>
做题感悟 :区域赛过后就没写过树剖 ,只记得思想,比赛时想到了,但是只打代码就打了半个多小时(真是醉了!!),然后就是不断的调试代码,悲催的是调了一个多小时也没调出来。。。。。
解题思路:这题只要想到某个节点的子树的所有节点编号都大于此节点的编号(在线段树中的位置的编号,树剖的时候编号都是连续的)且是连续的,那么我们只要深搜的时候记录一下子树最大的一...
做题感悟 :区域赛过后就没写过树剖 ,只记得思想,比赛时想到了,但是只打代码就打了半个多小时(真是醉了!!),然后就是不断的调试代码,悲催的是调了一个多小时也没调出来。。。。。
解题思路:这题只要想到某个节点的子树的所有节点编号都大于此节点的编号(在线段树中的位置的编号,树剖的时候编号都是连续的)且是连续的,那么我们只要深搜的时候记录一下子树最大的一个子节点的时间戳(在线段树中的编号),只要我们利用一个节点的进去的时间戳和出去的时间戳就可以对这个节点的子树操作了(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 ;
}
文章来源: blog.csdn.net,作者:Linux猿,版权归原作者所有,如需转载,请联系作者。
原文链接:blog.csdn.net/nyist_zxp/article/details/45457685
【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱:
cloudbbs@huaweicloud.com
- 点赞
- 收藏
- 关注作者
评论(0)