树剖+树状数组套线段树O(nlogn^3)(我打的),有一种更加优秀的算法是O(nlogn^2)的就是直接树状数组套线段树欧拉序(并不快),或者是用主席树维护原始的树的信息,同时用树状数组套线段树维护dfs序上的修改(很优秀),这道题将树上信息转化为序列信息,并在此基础之上用任意树套树,只不过转化的方式不一样,要么是树剖,要么是树上差分(dfs序或者欧拉序都可以)

#include <cstdio>
#include <cstring>
#include <algorithm>
#define mid ((l+r)>>1)
#define newnode (node+(sz++))
const int N=;
const int Inf=;
char xB[(<<)+],*xS=xB,*xTT=xB;
#define gtc() (xS==xTT&&(xTT=(xS=xB)+fread(xB,1,1<<15,stdin),xS==xTT)?0:*xS++)
inline void read(int &sum){
register char ch=gtc();
for(sum=;ch<''||ch>'';ch=gtc());
for(;ch>=''&&ch<='';sum=(sum<<)+(sum<<)+ch-'',ch=gtc());
}
struct Segment_Tree{
Segment_Tree *ch[];
int size;
}node[N*],*add[N],*red[N],*null,*root[N];
int cnt1,cnt2;
int n,cnt;
int val[N];
struct V{
int to,next;
}c[N<<];
int head[N],t,sz;
int ote[N],weight[N],deep[N],size[N];
int Ti,top[N],dfn[N],id[N];
inline void Init(){
null=newnode;
null->ch[]=null->ch[]=null;
null->size=;
for(int i=;i<=n;++i)root[i]=null;
}
inline void U1(Segment_Tree *&p,int l,int r,int pos){
--p->size;
if(l==r)return;
if(pos<=mid)U1(p->ch[],l,mid,pos);
else U1(p->ch[],mid+,r,pos);
}
inline void U2(Segment_Tree *&p,int l,int r,int pos){
if(p==null)p=newnode,p->ch[]=p->ch[]=null,p->size=;
++p->size;
if(l==r)return;
if(pos<=mid)U2(p->ch[],l,mid,pos);
else U2(p->ch[],mid+,r,pos);
}
inline int Q(int l,int r,int k){
if(l==r)return l;
register int sum=,i;
for(i=;i<=cnt1;++i)
sum+=add[i]->ch[]->size;
for(i=;i<=cnt2;++i)
sum-=red[i]->ch[]->size;
if(sum>=k){
for(i=;i<=cnt1;++i)
add[i]=add[i]->ch[];
for(i=;i<=cnt2;++i)
red[i]=red[i]->ch[];
return Q(mid+,r,k);
}else{
for(i=;i<=cnt1;++i)
add[i]=add[i]->ch[];
for(i=;i<=cnt2;++i)
red[i]=red[i]->ch[];
return Q(l,mid,k-sum);
}
}
inline void Q1(int pos){
for(;pos>;pos-=pos&(-pos))
add[++cnt1]=root[pos],cnt+=root[pos]->size;
}
inline void Q2(int pos){
for(;pos>;pos-=pos&(-pos))
red[++cnt2]=root[pos],cnt-=root[pos]->size;
}
inline void U(int pos,int val0,int val){
for(;pos<=n;pos+=pos&(-pos))
U1(root[pos],,Inf,val0),U2(root[pos],,Inf,val);
}
inline void U(int pos,int val){
for(;pos<=n;pos+=pos&(-pos))
U2(root[pos],,Inf,val);
}
inline void addedge(int x,int y){
c[++t].to=y,c[t].next=head[x],head[x]=t;
}
inline void dfs1(int x,int OPai){
ote[x]=OPai,deep[x]=deep[OPai]+;
size[x]=;
for(int i=head[x];i;i=c[i].next)
if(c[i].to!=OPai){
dfs1(c[i].to,x);
size[x]+=size[c[i].to];
if(size[c[i].to]>size[weight[x]])
weight[x]=c[i].to;
}
}
inline void dfs2(int x,int tp){
dfn[x]=++Ti,id[Ti]=x,top[x]=tp;
if(weight[x]==)return;
dfs2(weight[x],tp);
for(int i=head[x];i;i=c[i].next)
if(c[i].to!=ote[x]&&c[i].to!=weight[x])
dfs2(c[i].to,c[i].to);
}
inline void Q(int x,int y){
while(top[x]!=top[y]){
if(deep[top[x]]<deep[top[y]])std::swap(x,y);
Q1(dfn[x]),Q2(dfn[top[x]]-);
x=ote[top[x]];
}
if(deep[x]<deep[y])std::swap(x,y);
Q1(dfn[x]),Q2(dfn[y]-);
}
int main(){
int T;
read(n),read(T),Init();
for(int i=;i<=n;++i)read(val[i]);
for(int i=,x,y;i<n;++i){
read(x),read(y);
addedge(x,y),addedge(y,x);
}
dfs1(,),dfs2(,);
for(int i=;i<=n;++i)
U(dfn[i],val[i]);
int k,a,b;
while(T--){
read(k),read(a),read(b);
if(k==){
U(dfn[a],val[a],b),val[a]=b;
continue;
}
cnt1=cnt2=;
cnt=,Q(a,b);
if(cnt<k){
puts("invalid request!");
continue;
}
printf("%d\n",Q(,Inf,k));
}return ;
}

【BZOJ 1146】[CTSC2008]网络管理Network的更多相关文章

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

    1146: [CTSC2008]网络管理Network Time Limit: 50 Sec  Memory Limit: 162 MBSubmit: 3522  Solved: 1041[Submi ...

  2. BZOJ 1146: [CTSC2008]网络管理Network 树链剖分+线段树+平衡树

    1146: [CTSC2008]网络管理Network Time Limit: 50 Sec  Memory Limit: 162 MBSubmit: 870  Solved: 299[Submit] ...

  3. BZOJ 1146: [CTSC2008]网络管理Network( 树链剖分 + 树状数组套主席树 )

    树链剖分完就成了一道主席树裸题了, 每次树链剖分找出相应区间然后用BIT+(可持久化)权值线段树就可以完成计数. 但是空间问题很严重....在修改时不必要的就不要新建, 直接修改原来的..详见代码. ...

  4. bzoj 1146 [CTSC2008]网络管理Network

    很久之前写过 count on the tree. 然后一直不懂树状数组是怎么套上这个主席树的. 看了两小时发现它套的就是个权值线段树, 看不出来可持久化在哪里. 因为动态开点所以空间nlog2n. ...

  5. BZOJ 1146: [CTSC2008]网络管理Network 带修改主席树_树套树_DFS序

    Description M公司是一个非常庞大的跨国公司,在许多国家都设有它的下属分支机构或部门.为了让分布在世界各地的N个 部门之间协同工作,公司搭建了一个连接整个公司的通信网络.该网络的结构由N个路 ...

  6. [BZOJ 1146] [CTSC2008]网络管理Network(树状数组+主席树)

    题目描述 M公司是一个非常庞大的跨国公司,在许多国家都设有它的下属分支机构或部门.为了让分布在世界各地的N个部门之间协同工作,公司搭建了一个连接整个公司的通信网络.该网络的结构由N个路由器和N-1条高 ...

  7. 【BZOJ】1146: [CTSC2008]网络管理Network(树链剖分+线段树套平衡树+二分 / dfs序+树状数组+主席树)

    http://www.lydsy.com/JudgeOnline/problem.php?id=1146 第一种做法(时间太感人): 第二种做法(rank5,好开心) ================ ...

  8. 洛谷 P4175: bzoj 1146: [CTSC2008]网络管理

    令人抓狂的整体二分题.根本原因还是我太菜了. 在学校写了一个下午写得头晕,回家里重写了一遍,一个小时就写完了--不过还是太慢. 题目传送门:洛谷P4175. 题意简述: 一棵 \(n\) 个结点的树, ...

  9. [BZOJ1146][CTSC2008]网络管理Network

    [BZOJ1146][CTSC2008]网络管理Network 试题描述 M公司是一个非常庞大的跨国公司,在许多国家都设有它的下属分支机构或部门.为了让分布在世界各地的N个 部门之间协同工作,公司搭建 ...

  10. Luogu4175:[CTSC2008]网络管理Network

    题面 Luogu4175:[CTSC2008]网络管理Network Sol 路径第\(k\)大 无解直接判断就好了 然后整体二分,加上树链剖分+树状数组统计 # include <bits/s ...

随机推荐

  1. 微信小程序横向滚动

    <scroll-view scroll-x="true" style=" white-space: nowrap; display: flex" > ...

  2. vi-vim常用命令

    vi-vim常用命令 1 简介 在UNIX系统中,创建和修改配置文件.shell脚本.初始化文件.编写程序都离不开VI. 1      vi[1]属于两个主要的UNIX规范:POSIX和单一UNIX规 ...

  3. 通过SVI实现VLAN间通信

    两个不同网段的计算机与三层交换机直连,通过SVI实现VLAN间通信vlan 1 //几个不同网段就创建几个VLANvlan 2 int f0/1 //划分VLANswitchport mode acc ...

  4. poj_2339

    参考:https://blog.csdn.net/yzl_rex/article/details/7600906 https://blog.csdn.net/acm_JL/article/detail ...

  5. [Cracking the Coding Interview] 4.3 List of Depths

    Given a binary tree, design an algorithm which creates a linked list of all the nodes at each depth. ...

  6. linux挂载命令mount及U盘、移动硬盘的挂载

    一.mount的命令格式是(注意mount只能在root权限下运行) mount dervice dir dervice是要挂载的设备,dir是挂载点 二.查看当前磁盘列表的设备 fdisk -l 显 ...

  7. 利尔达CC3200模块烧写程序笔记

    1. 硬件使用利尔达的CC3200模块,仿真下载器使用利尔达的FTDI仿真器,硬件完全兼容官方的仿真器.仿真器支持IAR的调试,单步运行等操作. 2. 硬件连接接线说明: RXD, TXD, GNG, ...

  8. laravel5.5jwt-auth的使用

    laravel5.5 + jwt-auth:dev-develop 安装扩展 composer require tymon/jwt-auth:dev-develop --prefer-source 添 ...

  9. Objective-C反射机制

    oc反射机制有三个用途: 1.获得Class Class LoginViewController = NSClassFromString(@"LoginViewController" ...

  10. scidb

    貌似是给科学家用的数据库,暂不研究