http://www.elijahqi.win/2018/02/27/bzoj1146/
Description
M公司是一个非常庞大的跨国公司,在许多国家都设有它的下属分支机构或部门。为了让分布在世界各地的N个
部门之间协同工作,公司搭建了一个连接整个公司的通信网络。该网络的结构由N个路由器和N-1条高速光缆组成。
每个部门都有一个专属的路由器,部门局域网内的所有机器都联向这个路由器,然后再通过这个通信子网与其他部
门进行通信联络。该网络结构保证网络中的任意两个路由器之间都存在一条直接或间接路径以进行通信。 高速光
缆的数据传输速度非常快,以至于利用光缆传输的延迟时间可以忽略。但是由于路由器老化,在这些路由器上进行
数据交换会带来很大的延迟。而两个路由器之间的通信延迟时间则与这两个路由器通信路径上所有路由器中最大的
交换延迟时间有关。作为M公司网络部门的一名实习员工,现在要求你编写一个简单的程序来监视公司的网络状况
。该程序能够随时更新网络状况的变化信息(路由器数据交换延迟时间的变化),并且根据询问给出两个路由器通
信路径上延迟第k大的路由器的延迟时间。【任务】 你的程序从输入文件中读入N个路由器和N-1条光缆的连接信息
,每个路由器初始的数据交换延迟时间Ti,以及Q条询问(或状态改变)的信息。并依次处理这Q条询问信息,它们
可能是: 1. 由于更新了设备,或者设备出现新的故障,使得某个路由器的数据交换延迟时间发生了变化。 2. 查
询某两个路由器a和b之间的路径上延迟第k大的路由器的延迟时间。
Input
第一行为两个整数N和Q,分别表示路由器总数和询问的总数。
第二行有N个整数,第i个数表示编号为i的路由器初始的数据延迟时间Ti。
紧接着N-1行,每行包含两个整数x和y。表示有一条光缆连接路由器x和路由器y。
紧接着是Q行,每行三个整数k、a、b。
如果k=0,则表示路由器a的状态发生了变化,它的数据交换延迟时间由Ta变为b
如果k>0,则表示询问a到b的路径上所经过的所有路由器(包括a和b)中延迟
第k大的路由器的延迟时间。
注意N,Q<=80000,任意一个路由器在任何时刻都满足延迟时间小于10^8。
对于所有询问满足0<=K<=N
Output
对于每一个第二种询问(k>0),输出一行。包含一个整数为相应的延迟时间。
如果路径上的路由器不足k个,则输出信息“invalidrequest!”
(全部小写不包含引号,两个单词之间有一个空格)。
Sample Input
5 5
5 1 2 3 4
3 1
2 1
4 3
5 3
2 4 5
0 1 2
2 2 3
2 1 4
3 3 5
Sample Output
3
2
2
invalid request!
有个显然的做法 树链剖分加树套树 复杂度log^4 据说可过 但我写不出来??
学习了新的写法 同理 dfs的时候按照fa建立主席树 但是有修改怎么办 可以知道我们是可以用树状数组做差分的 所以同理再开n棵 线段树 用于差分 每次询问的时候在这差分区间的线段树 还有我的主席树上跑二分求排名即可 插入的时候 因为这个是按照dfs序列建 的前缀和 所以并不能直接用a[x] 应该将其从主程序传递过来
#include<cstdio>
#include<algorithm>
#define N 88000
using namespace std;
inline char gc(){
static char now[1<<16],*S,*T;
if (T==S){T=(S=now)+fread(now,1,1<<16,stdin);if (T==S) return EOF;}
return *S++;
}
inline int read(){
int x=0,f=1;char ch=gc();
while(ch<'0'||ch>'9') {if (ch=='-') f=-1;ch=gc();}
while(ch<='9'&&ch>='0') x=x*10+ch-'0',ch=gc();
return x*f;
}
struct node1{
int k,a,b;
}qr[N];
struct node{
int s,left,right;
}tree[200*N];
struct node2{
int y,next;
}data[N<<1];
int q,cnt,q1[N],q2[N],a1[N<<1],a[N],Log[N],dep[N],fa[N][20],rt[N],num,in[N],out[N],n1,n2,h[N],nn,n,bit_rt[N];
inline void insert1(int &x,int l,int r,int p){
tree[++cnt]=tree[x];x=cnt;++tree[x].s;int mid=l+r>>1;
if (l==r) return;if (p<=mid) insert1(tree[x].left,l,mid,p);
else insert1(tree[x].right,mid+1,r,p);
}
inline void dfs(int x){
in[x]=++num;rt[x]=rt[fa[x][0]];insert1(rt[x],1,nn,a[x]);
for (int i=h[x];i;i=data[i].next){
int y=data[i].y;if(y==fa[x][0]) continue;
fa[y][0]=x;dep[y]=dep[x]+1;
for (int j=1;j<=Log[dep[y]];++j) fa[y][j]=fa[fa[y][j-1]][j-1];dfs(y);
}out[x]=num;
}
inline void ins(int &x,int l,int r,int p,int v){
if (!x) x=++cnt;tree[x].s+=v;int mid=l+r>>1;
if (l==r) return;if (p<=mid) ins(tree[x].left,l,mid,p,v);
else ins(tree[x].right,mid+1,r,p,v);
}
inline int lca(int x,int y){
if (dep[x]<dep[y]) swap(x,y);
int dis=dep[x]-dep[y];
for (int i=0;i<=Log[dis];++i) if ((1<<i)&dis) x=fa[x][i];
if (x==y) return x;
for (int i=Log[dep[y]];~i;--i)
if (fa[x][i]!=fa[y][i]) x=fa[x][i],y=fa[y][i];
return fa[x][0];
}
inline void add(int x,int p,int v){for (int i=x;i<=n;i+=i&(-i)) ins(bit_rt[i],1,nn,p,v);}
inline void init1(int x){for (;x;x-=x&(-x)) q1[++n1]=bit_rt[x];}
inline void init2(int x){for (;x;x-=x&(-x)) q2[++n2]=bit_rt[x];}
inline int qk(int l,int r,int k){
if (l==r) return l;int mid=l+r>>1,sz=0;
for (int i=1;i<=n1;++i) sz-=tree[tree[q1[i]].left].s;
for (int i=1;i<=n2;++i) sz+=tree[tree[q2[i]].left].s;
if (k<=sz) {
for (int i=1;i<=n1;++i) q1[i]=tree[q1[i]].left;
for (int i=1;i<=n2;++i) q2[i]=tree[q2[i]].left;
return qk(l,mid,k);
}for (int i=1;i<=n1;++i) q1[i]=tree[q1[i]].right;
for (int i=1;i<=n2;++i) q2[i]=tree[q2[i]].right;
return qk(mid+1,r,k-sz);
}
int main(){
freopen("bzoj1146.in","r",stdin);
n=read();q=read();nn=n;Log[0]=-1;
for (int i=1;i<=n;++i) a1[i]=a[i]=read();
for (int i=1;i<n;++i) {
int x=read(),y=read();
data[++num].y=y;data[num].next=h[x];h[x]=num;
data[++num].y=x;data[num].next=h[y];h[y]=num;
}num=0;for (int i=1;i<=n;++i) Log[i]=Log[i>>1]+1;
for (int i=1;i<=q;++i) {
qr[i].k=read();qr[i].a=read();qr[i].b=read();
if (!qr[i].k) a1[++nn]=qr[i].b;
}sort(a1+1,a1+nn+1);nn=unique(a1+1,a1+nn+1)-a1-1;
for (int i=1;i<=n;++i) a[i]=lower_bound(a1+1,a1+nn+1,a[i])-a1;
dfs(1);
for (int i=1;i<=q;++i){
if (!qr[i].k){
add(in[qr[i].a],a[qr[i].a],-1);add(out[qr[i].a]+1,a[qr[i].a],1);
a[qr[i].a]=lower_bound(a1+1,a1+nn+1,qr[i].b)-a1;
add(in[qr[i].a],a[qr[i].a],1);add(out[qr[i].a]+1,a[qr[i].a],-1);continue;
}n1=n2=0;int x=qr[i].a,y=qr[i].b,t=lca(x,y),f=fa[t][0],sz=0;init1(in[t]);init1(in[f]);
q2[++n2]=rt[x];q2[++n2]=rt[y];q1[++n1]=rt[t];q1[++n1]=rt[f];init2(in[x]);init2(in[y]);
for (int ii=1;ii<=n1;++ii) sz-=tree[q1[ii]].s;
for (int ii=1;ii<=n2;++ii) sz+=tree[q2[ii]].s;
if (sz<qr[i].k) {puts("invalid request!");continue;}qr[i].k=sz-qr[i].k+1;
printf("%d\n",a1[qk(1,nn,qr[i].k)]);
}
return 0;
}