BZOJ1146 [CTSC2008]网络管理Network 树链剖分 主席树 树状数组

欢迎访问~原文出处——博客园-zhouzhendong

去博客园看该题解


题目传送门 - BZOJ1146


题意概括

  在一棵树上,每一个点一个权值。

  有两种操作:

  1、单点修改

  2、询问两点之间的树链上的第k大值


题解

  水题。

  就是烦了一点。

  树链剖分+带修主席树。

  带修主席树:

  BZOJ1901 Zju2112 Dynamic Rankings 主席树


代码

#include <cstring>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstdlib>
#include <vector>
using namespace std;
const int N=80005;
struct Gragh{
	int cnt,y[N*2],nxt[N*2],fst[N];
	void clear(){
		cnt=0;
		memset(fst,0,sizeof fst);
	}
	void add(int a,int b){
		y[++cnt]=b,nxt[cnt]=fst[a],fst[a]=cnt;
	}
}g;
struct cz{
	int k,a,b;
}q[N];
int n,Q,v[N],Ha[N*2],hs;
int fa[N],son[N],depth[N],size[N],top[N],p[N],ap[N],cnp=0;
const int S=N*2*2*20;
vector <int> val[N];
int ls[S],rs[S],root[N],Next[S],sum[S],pp[S],app[S],tot=0,tpp=0;
void LSH(){
	sort(Ha+1,Ha+hs+1);
	int hs_=1;
	for (int i=2;i<=hs;i++)
		if (Ha[i]!=Ha[i-1])
			Ha[++hs_]=Ha[i];
	hs=hs_;
}
void Get_Gen_Info(int rt,int pre,int d){
	fa[rt]=pre,depth[rt]=d,size[rt]=1,son[rt]=-1;
	for (int i=g.fst[rt];i;i=g.nxt[i])
		if (g.y[i]!=pre){
			int s=g.y[i];
			Get_Gen_Info(s,rt,d+1);
			size[rt]+=size[s];
			if (son[rt]==-1||size[s]>size[son[rt]])
				son[rt]=s;
		}
}
void Get_Top(int rt,int tp){
	top[rt]=tp;
	ap[p[rt]=++cnp]=rt;
	if (son[rt]==-1)
		return;
	Get_Top(son[rt],tp);
	for (int i=g.fst[rt];i;i=g.nxt[i]){
		int s=g.y[i];
		if (s!=fa[rt]&&s!=son[rt])
			Get_Top(s,s);
	}
}
int find(int x){
	return lower_bound(Ha+1,Ha+hs+1,x)-Ha;
}
void build(int &rt,int L,int R){
	rt=++tot;
	if (L==R){
		ls[rt]=rs[rt]=0;
		return;
	}
	int mid=(L+R)>>1;
	build(ls[rt],L,mid);
	build(rs[rt],mid+1,R);
}
void access(int prt,int &rt,int L,int R,int pos){
	if (!rt||rt==prt)
		rt=++tot;
	Next[prt]=rt;
	if (L==R)
		return;
	int mid=(L+R)>>1;
	if (pos<=mid){
		access(ls[prt],ls[rt],L,mid,pos);
		if (!rs[rt])
			rs[rt]=rs[prt];
	}
	else {
		access(rs[prt],rs[rt],mid+1,R,pos);
		if (!ls[rt])
			ls[rt]=ls[prt];
	}
}
void build_pp(int rt){
	if (!rt)
		return;
	for (int i=rt;i;i=Next[i])
		app[pp[i]=++tpp]=i;
	build_pp(ls[rt]);
	build_pp(rs[rt]);
}
int lowbit(int x){
	return x&-x;
}
void add(int x,int d){
	for (;x<=tpp;x+=lowbit(x))
		sum[x]+=d;
}
int Sum(int x){
	int ans=0;
	for (;x>0;x-=lowbit(x))
		ans+=sum[x];
	return ans;
}
void update(int rt,int L,int R,int pos,int v){
	add(pp[rt],v);
	if (L==R)
		return;
	int mid=(L+R)>>1;
	if (pos<=mid)
		update(ls[rt],L,mid,pos,v);
	else
		update(rs[rt],mid+1,R,pos,v);
}
int query(int prt,int rt,int L,int R,int pos){
	if (R<pos)
		return 0;
	if (L>=pos)
		return Sum(pp[rt])-Sum(pp[prt]);
	int mid=(L+R)>>1;
	return query(ls[prt],ls[rt],L,mid,pos)+query(rs[prt],rs[rt],mid+1,R,pos);
}
int Tquery(int a,int b,int pos){
	int f1=top[a],f2=top[b];
	int total=0;
	while (f1!=f2){
		if (depth[f1]<depth[f2])
			swap(f1,f2),swap(a,b);
		total+=query(root[p[f1]-1],root[p[a]],1,hs,pos);
		a=fa[f1],f1=top[a];
	}
	if (depth[a]>depth[b])
		swap(a,b);
	total+=query(root[p[a]-1],root[p[b]],1,hs,pos);
	return total;
}
int main(){
	scanf("%d%d",&n,&Q);
	for (int i=1;i<=n;i++)
		scanf("%d",&v[i]),Ha[i]=v[i];
	hs=n;
	g.clear();
	for (int i=1,a,b;i<n;i++){
		scanf("%d%d",&a,&b);
		g.add(a,b);
		g.add(b,a);
	}
	for (int i=1;i<=Q;i++){
		scanf("%d%d%d",&q[i].k,&q[i].a,&q[i].b);
		if (q[i].k==0)
			Ha[++hs]=q[i].b;
	}
	LSH();
	Get_Gen_Info(1,0,0);
	Get_Top(1,1);
	for (int i=1;i<=n;i++)
		val[i].clear();
	for (int i=1;i<=n;i++)
		val[p[i]].push_back(find(v[i]));
	for (int i=1;i<=Q;i++)
		if (q[i].k==0)
			val[p[q[i].a]].push_back(find(q[i].b));
	build(root[0],1,hs);
	memset(Next,0,sizeof Next);
	for (int i=1;i<=n;i++)
		for (int j=0;j<val[i].size();j++)
			access(root[i-1],root[i],1,hs,val[i][j]);
	build_pp(root[0]);
	memset(sum,0,sizeof sum);
	for (int i=1;i<=n;i++)
		update(root[p[i]],1,hs,find(v[i]),1);
	for (int i=1;i<=Q;i++){
		if (q[i].k==0){
			update(root[p[q[i].a]],1,hs,find(v[q[i].a]),-1);
			update(root[p[q[i].a]],1,hs,find(v[q[i].a]=q[i].b),1);
		}
		else {
			int L=1,R=hs,mid,ans=-1;
			while (L<=R){
				mid=(L+R)>>1;
				if (Tquery(q[i].a,q[i].b,mid)>=q[i].k)
					L=mid+1,ans=mid;
				else
					R=mid-1;
			}
			if (!~ans)
				puts("invalid request!");
			else
				printf("%d\n",Ha[ans]);
		}
	}
	return 0;
}

  

时间: 2024-10-29 10:45:43

BZOJ1146 [CTSC2008]网络管理Network 树链剖分 主席树 树状数组的相关文章

bzoj1146 [CTSC2008]网络管理Network

Description M公司是一个非常庞大的跨国公司,在许多国家都设有它的下属分支机构或部门.为了让分布在世界各地的N个部门之间协同工作,公司搭建了一个连接整个公司的通信网络.该网络的结构由N个路由器和N-1条高速光缆组成.每个部门都有一个专属的路由器,部门局域网内的所有机器都联向这个路由器,然后再通过这个通信子网与其他部门进行通信联络.该网络结构保证网络中的任意两个路由器之间都存在一条直接或间接路径以进行通信. 高速光缆的数据传输速度非常快,以至于利用光缆传输的延迟时间可以忽略.但是由于路由

poj 3237 Tree(树链剖分,线段树)

Tree Time Limit: 5000MS   Memory Limit: 131072K Total Submissions: 7268   Accepted: 1969 Description You are given a tree with N nodes. The tree’s nodes are numbered 1 through N and its edges are numbered 1 through N − 1. Each edge is associated with

bzoj 3626 [LNOI2014]LCA(离线处理+树链剖分,线段树)

3626: [LNOI2014]LCA Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1272  Solved: 451[Submit][Status][Discuss] Description 给出一个n个节点的有根树(编号为0到n-1,根节点为0).一个点的深度定义为这个节点到根的距离+1. 设dep[i]表示点i的深度,LCA(i,j)表示i与j的最近公共祖先. 有q次询问,每次询问给出l r z,求sigma_{l<=i<=r}dep[

bzoj 1036 [ZJOI2008]树的统计Count(树链剖分,线段树)

1036: [ZJOI2008]树的统计Count Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 10677  Solved: 4313[Submit][Status][Discuss] Description 一 棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w.我们将以下面的形式来要求你对这棵树完成一些操作: I. CHANGE u t : 把结点u的权值改为t II. QMAX u v: 询问从点u到点v的路径上的节点的最大权值

HDU - 3966 Aragorn&#39;s Story(树链剖分入门+线段树)

HDU - 3966 Aragorn's Story Time Limit: 3000MS   Memory Limit: 32768KB   64bit IO Format: %I64d & %I64u Submit Status Description Our protagonist is the handsome human prince Aragorn comes from The Lord of the Rings. One day Aragorn finds a lot of ene

BZOJ 1146: [CTSC2008]网络管理Network [树上带修改主席树]

1146: [CTSC2008]网络管理Network Time Limit: 50 Sec  Memory Limit: 162 MBSubmit: 3522  Solved: 1041[Submit][Status][Discuss] Description M公司是一个非常庞大的跨国公司,在许多国家都设有它的下属分支机构或部门.为了让分布在世界各地的N个 部门之间协同工作,公司搭建了一个连接整个公司的通信网络.该网络的结构由N个路由器和N-1条高速光缆组成. 每个部门都有一个专属的路由器,

hdu 6162 Ch’s gift(树链剖分+主席树)

题目链接:hdu 6162 Ch's gift 题意: 给你一棵树,树上每个点有一个权值,现在有m个询问,每次询问给你一个s,t,L,R,问你从s到t的路径上,权值在[L,R]内的总和为多少. 题解: 我感觉我写复杂了,用树链剖分来维护路径,然后用主席树来建立权值线段树乱搞. 1 #include<bits/stdc++.h> 2 #define mst(a,b) memset(a,b,sizeof(a)) 3 #define F(i,a,b) for(int i=(a);i<=(b);

BZOJ3531 SDOI2014 旅行 - 树链剖分,主席树

题意:给定一棵树,树上每个点有权值和类型.支持:修改某个点的类型:修改某个点的权值:询问某条链上某个类型的点的和/最大值.点数/类型数/询问数<=100000. 分析: 树链剖分,对每个类型的点建立线段树(动态开点). note: 忘记写t_query返回值调半天-- 莫名其妙地1A 代码: 1 #include <bits/stdc++.h> 2 using namespace std; 3 4 int a[5000005],s[5000005],dep[100005],size[10

bzoj 3531 [Sdoi2014]旅行(树链剖分,线段树)

3531: [Sdoi2014]旅行 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 876  Solved: 446[Submit][Status][Discuss] Description S国有N个城市,编号从1到N.城市间用N-1条双向道路连接,满足 从一个城市出发可以到达其它所有城市.每个城市信仰不同的宗教,如飞天面条神教.隐形独角兽教.绝地教都是常见的信仰.为了方便,我们用不同的正整数代表 各种宗教,  S国的居民常常旅行.旅行时他们总