BZOJ 1146: [CTSC2008]网络管理Network 带修改主席树_树套树_DFS序
Description
Input
Output
题解:
树套树.
之前做过不带修改的,感觉还挺容易的.
这次是带修改版本,就不能直接在树上建主席树了.
不同的是,我们对 $DFS$ 序建立主席树
考虑到每一次修改一个点,只会对该点的子树到根的路径产生影响.
在 DFS 序中,每个点的子树是一段连续的区间,直接用带修改主席树修改一波即可.
在 DFS 序中,每个点到根节点的路径和就是该点在 DFS 序中的前缀和.
这样进行修改和查询即可.
Code:
#include<bits/stdc++.h>
#define setIO(s) freopen(s".in","r",stdin) ,freopen(s".out","w",stdout)
#define maxn 200000
#define N 180000
using namespace std;
int n,q, edges,cc,num;
//权值线段树
namespace Seg
{
#define mid ((l+r)>>1)
int rt[maxn],node[10][maxn],cnt[10];
int tot;
struct Node
{
int l,r,w;
}t[maxn*50];
void insert(int &x,int l,int r,int k,int delta)
{
if(!x) x=++tot;
t[x].w+=delta;
if(l==r) return;
if(k<=mid)
insert(t[x].l,l,mid,k,delta);
else
insert(t[x].r,mid+1,r,k,delta);
}
int lowbit(int t)
{
return t & (-t);
}
void update(int pos,int val,int delta)
{
while(pos<=N) insert(rt[pos],1,N,val,delta),pos+=lowbit(pos);
}
int query(int l,int r,int kth)
{
if(l==r) return l;
int sum=0;
for(int i=1;i<=cnt[0];++i) sum+=t[t[node[0][i]].r].w;
for(int i=1;i<=cnt[1];++i) sum+=t[t[node[1][i]].r].w;
for(int i=1;i<=cnt[2];++i) sum-=t[t[node[2][i]].r].w;
for(int i=1;i<=cnt[3];++i) sum-=t[t[node[3][i]].r].w;
if(sum < kth)
{
for(int i=1;i<=cnt[0];++i) node[0][i] = t[node[0][i]].l;
for(int i=1;i<=cnt[1];++i) node[1][i] = t[node[1][i]].l;
for(int i=1;i<=cnt[2];++i) node[2][i] = t[node[2][i]].l;
for(int i=1;i<=cnt[3];++i) node[3][i] = t[node[3][i]].l;
return query(l,mid,kth-sum);
}
else
{
for(int i=1;i<=cnt[0];++i) node[0][i] = t[node[0][i]].r;
for(int i=1;i<=cnt[1];++i) node[1][i] = t[node[1][i]].r;
for(int i=1;i<=cnt[2];++i) node[2][i] = t[node[2][i]].r;
for(int i=1;i<=cnt[3];++i) node[3][i] = t[node[3][i]].r;
return query(mid+1,r,kth);
}
}
// 关键字 : 位置
int Query(int a,int b,int c,int d,int kth)
{
cnt[0]=cnt[1]=cnt[2]=cnt[3]=0;
for(int i=a;i>0;i-=lowbit(i)) node[0][++cnt[0]] = rt[i];
for(int i=b;i>0;i-=lowbit(i)) node[1][++cnt[1]] = rt[i];
for(int i=c;i>0;i-=lowbit(i)) node[2][++cnt[2]] = rt[i];
for(int i=d;i>0;i-=lowbit(i)) node[3][++cnt[3]] = rt[i];
return query(1,N,kth);
}
};
struct Query
{
int opt,a,b;
}Q[maxn];
int hd[maxn],to[maxn],nex[maxn],dfs[maxn],arr[maxn],A[maxn];
int st[maxn],ed[maxn],F[20][maxn],dep[maxn],val[maxn];
void add(int u,int v)
{
nex[++edges]=hd[u],hd[u]=edges,to[edges]=v;
}
//read and diskreat
void read()
{
scanf("%d%d",&n,&q);
for(int i=1;i<=n;++i) scanf("%d",&val[i]),A[++cc]=val[i];
for(int i=1,a,b;i<n;++i)
scanf("%d%d",&a,&b), add(a,b),add(b,a);
for(int i=1;i<=q;++i)
{
scanf("%d%d%d",&Q[i].opt,&Q[i].a,&Q[i].b);
if(Q[i].opt==0) A[++cc]=Q[i].b;
}
sort(A+1,A+1+cc);
for(int i=1;i<=q;++i) if(Q[i].opt==0) Q[i].b=lower_bound(A+1,A+1+cc,Q[i].b)-A;
for(int i=1;i<=n;++i) val[i] = lower_bound(A+1,A+1+cc,val[i])-A;
}
//求dfs序
void DFS(int u,int fa)
{
F[0][u]=fa, dep[u] = dep[fa] + 1;
for(int i=1;i<20;++i) F[i][u]=F[i-1][F[i-1][u]];
dfs[++num]=val[u],st[u]=num;
for(int i=hd[u];i;i=nex[i])
{
if(to[i]==fa) continue;
DFS(to[i],u);
}
ed[u]=num+1;
}
int LCA(int a,int b)
{
if(dep[b]<dep[a]) swap(a,b);
if(dep[a]!=dep[b])
{
for(int i=19;i>=0;--i) if(dep[F[i][b]] >= dep[a]) b = F[i][b];
}
if(a==b) return a;
for(int i=19;i>=0;--i)
{
if(F[i][a]!=F[i][b]) a = F[i][a], b = F[i][b];
}
return F[0][a];
}
int main()
{
// setIO("input");
read();
DFS(1,0);
for(int i = 1;i <= n; ++i)
{
Seg::update(st[i],val[i], 1);
Seg::update(ed[i],val[i], -1);
}
for(int i=1,a,b;i<=q;++i)
{
a = Q[i].a, b = Q[i].b;
if(Q[i].opt==0)
{
Seg::update(st[a], val[a], -1);
Seg::update(ed[a], val[a], 1);
val[a] = b;
Seg::update(st[a],val[a], 1);
Seg::update(ed[a],val[a], -1);
}
if(Q[i].opt>0)
{
int lca = LCA(a,b);
int c = Seg::Query(st[a],st[b],st[lca],st[F[0][lca]],Q[i].opt);
if(c==1)
printf("invalid request!\n");
else
printf("%d\n",A[c]);
}
}
return 0;
}
BZOJ 1146: [CTSC2008]网络管理Network 带修改主席树_树套树_DFS序的更多相关文章
- BZOJ 1146: [CTSC2008]网络管理Network [树上带修改主席树]
1146: [CTSC2008]网络管理Network Time Limit: 50 Sec Memory Limit: 162 MBSubmit: 3522 Solved: 1041[Submi ...
- BZOJ 1146: [CTSC2008]网络管理Network( 树链剖分 + 树状数组套主席树 )
树链剖分完就成了一道主席树裸题了, 每次树链剖分找出相应区间然后用BIT+(可持久化)权值线段树就可以完成计数. 但是空间问题很严重....在修改时不必要的就不要新建, 直接修改原来的..详见代码. ...
- BZOJ 1146: [CTSC2008]网络管理Network 树链剖分+线段树+平衡树
1146: [CTSC2008]网络管理Network Time Limit: 50 Sec Memory Limit: 162 MBSubmit: 870 Solved: 299[Submit] ...
- [BZOJ 1146] [CTSC2008]网络管理Network(树状数组+主席树)
题目描述 M公司是一个非常庞大的跨国公司,在许多国家都设有它的下属分支机构或部门.为了让分布在世界各地的N个部门之间协同工作,公司搭建了一个连接整个公司的通信网络.该网络的结构由N个路由器和N-1条高 ...
- bzoj 1146 [CTSC2008]网络管理Network
很久之前写过 count on the tree. 然后一直不懂树状数组是怎么套上这个主席树的. 看了两小时发现它套的就是个权值线段树, 看不出来可持久化在哪里. 因为动态开点所以空间nlog2n. ...
- BZOJ 1901: Zju2112 Dynamic Rankings | 带修改主席树
题目: emmmm是个权限题 题解: 带修改主席树的板子题,核心思想是用树状数组维护动态前缀和的性质来支持修改 修改的时候修改类似树状数组一样进行logn个Insert 查询的时候同理,树状数组的方法 ...
- 洛谷 P4175: bzoj 1146: [CTSC2008]网络管理
令人抓狂的整体二分题.根本原因还是我太菜了. 在学校写了一个下午写得头晕,回家里重写了一遍,一个小时就写完了--不过还是太慢. 题目传送门:洛谷P4175. 题意简述: 一棵 \(n\) 个结点的树, ...
- 【BZOJ】1146: [CTSC2008]网络管理Network(树链剖分+线段树套平衡树+二分 / dfs序+树状数组+主席树)
http://www.lydsy.com/JudgeOnline/problem.php?id=1146 第一种做法(时间太感人): 第二种做法(rank5,好开心) ================ ...
- 【BZOJ1146】[CTSC2008]网络管理Network 树状数组+DFS序+主席树
[BZOJ1146][CTSC2008]网络管理Network Description M公司是一个非常庞大的跨国公司,在许多国家都设有它的下属分支机构或部门.为了让分布在世界各地的N个部门之间协同工 ...
随机推荐
- LinkedList,ArrayList末尾插入谁效率高?
废话不多说,原因不解释.上測试代码: package com.letv.cloud.cdn.jtest; import java.io.IOException; import java.util.Ar ...
- poj 2931 Building a Space Station <克鲁斯卡尔>
Building a Space Station Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 5869 Accepted: 2 ...
- Apache + Tomcat + JK 集群
原文请见http://www.cnblogs.com/dennisit/p/3370220.html 本文介绍了集群和负载均衡的基本开源实现,实现了用Apache分发请求到多个Tomcat里面相应的应 ...
- iOS UITableView 去除多余切割线
在UITableView初始化时加上下面代码就可以: self.tableView.tableFooterView = [[UIView alloc] initWithFrame:CGRectZero ...
- "Hello World " —— 深入理解程序从编译到执行
对于C语言编写的Hello World程序(例如以下).对于程序猿来说肯定如雷贯耳,就是这样一个简单的程序,你真的了解她吗? #include <stdio.h> int main() { ...
- nyoj860 又见01背包(背包变形)
题目860 pid=860" style="text-decoration:none; color:rgb(55,119,188)">题目信息 执行结果 本题排行 ...
- HDU 3656 二分+dlx判定
Fire station Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) To ...
- ExtJs 给grid某一单元格重新赋值
// 司机,搬运工提成 var commissionMoney = (waybillsFtQty * commissionMoneyRatio / personCount).toFixed(2); / ...
- K度限制MST poj 1639
/* k度限制MST:有一个点的度<=k的MST poj 1639 要求1号点的度不超过k 求MST 我们先把1号点扔掉 跑MST 假设有sum个连通分支 然后把这sum个分支连到1上 就得到了 ...
- 如何更改iTunes备份地址(修改iphone ipad 备份地址) itunes文件目录修改方法 【亲测有效,附带原理说明】
前言 C盘空间有限,但是iTunes就是那么龌龊,只能把手机备份存到C盘.那么怎么才能把备份文件存到其他分区的文件夹里面呢? 当时我想先看看度娘,看看有没有现成的! 结果 nnd!! 我看了一大堆相关 ...