裸题,直接上。复杂度O(n*sqrt(n)*log(n))。

//Num[i]表示树中的点i在函数式权值分块中对应的点
//Map[i]表示函数式权值分块中的点i在树中对应的点
#include<cstdio>
#include<algorithm>
#include<cmath>
using namespace std;
#define N 80001
#define INF 2147483647
#define NN 87001
#define BN 296
int x,y;
int fa[N],dep[N],siz[N],son[N],Num[N],tot,top[N],n,m,Ks[N],xs[N],ys[N],w[N];
int en,first[N],next[N<<1],v[N<<1];
int en2,en3,ma[NN],a[NN];
int l[BN],sum=1,r[BN],num[N];
int r2[NN],num2[NN],sum2=1;
struct Point{int p,v;}t[NN];
bool operator < (const Point &a,const Point &b){return a.v<b.v;}
struct Val_Block
{
int b[NN],sumv[BN];
void insert(const int &x){++b[x]; ++sumv[num2[x]];}
void erase(const int &x){--b[x]; --sumv[num2[x]];}
}T[285],S;
void AddEdge(const int &U,const int &V)
{
v[++en]=V;
next[en]=first[U];
first[U]=en;
}
void dfs(int U,int Fa,int d)
{
fa[U]=Fa;
dep[U]=d;
siz[U]=1;
for(int i=first[U];i;i=next[i])
if(v[i]!=fa[U])
{
dfs(v[i],U,d+1);
siz[U]+=siz[v[i]];
if(siz[v[i]]>siz[son[U]])
son[U]=v[i];
}
}
void dfs2(int U)
{
if(son[U])
{
top[son[U]]=top[U];
Num[son[U]]=++tot;
dfs2(son[U]);
}
for(int i=first[U];i;i=next[i])
if(v[i]!=fa[U]&&v[i]!=son[U])
{
top[v[i]]=v[i];
Num[v[i]]=++tot;
dfs2(v[i]);
}
}
void makeblock()
{
int sz=sqrt(n);
if(!sz) sz=1;
for(;sum*sz<n;++sum)
{
l[sum]=r[sum-1]+1;
r[sum]=sum*sz;
for(int i=l[sum];i<=r[sum];++i)
num[i]=sum;
}
l[sum]=r[sum-1]+1;
r[sum]=n;
for(int i=l[sum];i<=r[sum];++i)
num[i]=sum;
}
void val_mb()
{
int sz=sqrt(en3);
if(!sz) sz=1;
for(;sum2*sz<en3;++sum2)
{
r2[sum2]=sum2*sz;
for(int i=r2[sum2-1]+1;i<=r2[sum2];++i)
num2[i]=sum2;
}
r2[sum2]=en3;
for(int i=r2[sum2-1]+1;i<=r2[sum2];++i)
num2[i]=sum2;
}
void Init_Ts()
{
for(int i=1;i<=sum;++i)
{
T[i]=T[i-1];
for(int j=l[i];j<=r[i];++j)
T[i].insert(a[j]);
}
}
int Query(const int &x,const int &y,const int &K)
{
//构建零散部分的权值分块
int U=x,V=y,cnt=0,res=INF;
int f1=top[U],f2=top[V];
while(f1!=f2)
{
if(dep[f1]<dep[f2])
{
swap(U,V);
swap(f1,f2);
}
if(num[Num[f1]]+1>=num[Num[U]])
for(int i=Num[f1];i<=Num[U];++i)
S.insert(a[i]);
else
{
for(int i=Num[f1];i<=r[num[Num[f1]]];++i)
S.insert(a[i]);
for(int i=l[num[Num[U]]];i<=Num[U];++i)
S.insert(a[i]);
}
U=fa[f1];
f1=top[U];
}
if(dep[U]>dep[V])
swap(U,V);
if(num[Num[U]]+1>=num[Num[V]])
for(int i=Num[U];i<=Num[V];++i)
S.insert(a[i]);
else
{
for(int i=Num[U];i<=r[num[Num[U]]];++i)
S.insert(a[i]);
for(int i=l[num[Num[V]]];i<=Num[V];++i)
S.insert(a[i]);
}
//计算答案
for(int i=sum2;i>=1;--i)
{
int tcnt=0;
U=x; V=y;
f1=top[U]; f2=top[V];
while(f1!=f2)
{
if(dep[f1]<dep[f2])
{
swap(U,V);
swap(f1,f2);
}
if(num[Num[f1]]+1<num[Num[U]])
tcnt+=T[num[Num[U]]-1].sumv[i]-T[num[Num[f1]]].sumv[i];
U=fa[f1];
f1=top[U];
}
if(dep[U]>dep[V])
swap(U,V);
if(num[Num[U]]+1<num[Num[V]])
tcnt+=T[num[Num[V]]-1].sumv[i]-T[num[Num[U]]].sumv[i];
tcnt+=S.sumv[i];
cnt+=tcnt;
if(cnt>=K)
{
cnt-=tcnt;
for(int j=r2[i];;--j)
{
U=x; V=y;
f1=top[U]; f2=top[V];
while(f1!=f2)
{
if(dep[f1]<dep[f2])
{
swap(U,V);
swap(f1,f2);
}
if(num[Num[f1]]+1<num[Num[U]])
cnt+=T[num[Num[U]]-1].b[j]-T[num[Num[f1]]].b[j];
U=fa[f1];
f1=top[U];
}
if(dep[U]>dep[V])
swap(U,V);
if(num[Num[U]]+1<num[Num[V]])
cnt+=T[num[Num[V]]-1].b[j]-T[num[Num[U]]].b[j];
cnt+=S.b[j];
if(cnt>=K)
{
res=j;
goto OUT;
}
}
}
}
OUT:
//清空零散部分的权值分块
U=x,V=y;
f1=top[U],f2=top[V];
while(f1!=f2)
{
if(dep[f1]<dep[f2])
{
swap(U,V);
swap(f1,f2);
}
if(num[Num[f1]]+1>=num[Num[U]])
for(int i=Num[f1];i<=Num[U];++i)
S.erase(a[i]);
else
{
for(int i=Num[f1];i<=r[num[Num[f1]]];++i)
S.erase(a[i]);
for(int i=l[num[Num[U]]];i<=Num[U];++i)
S.erase(a[i]);
}
U=fa[f1];
f1=top[U];
}
if(dep[U]>dep[V])
swap(U,V);
if(num[Num[U]]+1>=num[Num[V]])
for(int i=Num[U];i<=Num[V];++i)
S.erase(a[i]);
else
{
for(int i=Num[U];i<=r[num[Num[U]]];++i)
S.erase(a[i]);
for(int i=l[num[Num[V]]];i<=Num[V];++i)
S.erase(a[i]);
}
return res;
}
int main()
{
scanf("%d%d",&n,&m);
makeblock();
for(int i=1;i<=n;++i)
scanf("%d",&w[i]);
for(int i=1;i<n;++i)
{
scanf("%d%d",&x,&y);
AddEdge(x,y);
AddEdge(y,x);
}
top[1]=1;
Num[1]=++tot;
dfs(1,0,1);
dfs2(1);
for(int i=1;i<=n;++i)
{
t[Num[i]].v=w[i];
t[Num[i]].p=Num[i];
}
en2=n;
for(int i=1;i<=m;++i)
{
scanf("%d%d%d",&Ks[i],&xs[i],&ys[i]);
if(!Ks[i])
{
t[++en2].v=ys[i];
t[en2].p=en2;
}
}
sort(t+1,t+en2+1);
ma[a[t[1].p]=++en3]=t[1].v;
for(int i=2;i<=en2;++i)
{
if(t[i].v!=t[i-1].v) ++en3;
ma[a[t[i].p]=en3]=t[i].v;
}
val_mb();
Init_Ts();
en2=n;
for(int i=1;i<=m;++i)
{
if(Ks[i])
{
int ans=Query(xs[i],ys[i],Ks[i]);
if(ans==INF) puts("invalid request!");
else printf("%d\n",ma[ans]);
}
else
{
++en2;
for(int j=num[Num[xs[i]]];j<=sum;++j)
{
T[j].erase(a[Num[xs[i]]]);
T[j].insert(a[en2]);
}
a[Num[xs[i]]]=a[en2];
}
}
return 0;
}

【树链剖分】【函数式权值分块】bzoj1146 [CTSC2008]网络管理Network的更多相关文章

  1. 刷题总结——骑士的旅行(bzoj4336 树链剖分套权值线段树)

    题目: Description 在一片古老的土地上,有一个繁荣的文明. 这片大地几乎被森林覆盖,有N座城坐落其中.巧合的是,这N座城由恰好N-1条双 向道路连接起来,使得任意两座城都是连通的.也就是说 ...

  2. 计蒜客 38229.Distance on the tree-1.树链剖分(边权)+可持久化线段树(区间小于等于k的数的个数)+离散化+离线处理 or 2.树上第k大(主席树)+二分+离散化+在线查询 (The Preliminary Contest for ICPC China Nanchang National Invitational 南昌邀请赛网络赛)

    Distance on the tree DSM(Data Structure Master) once learned about tree when he was preparing for NO ...

  3. BZOJ 1036 [ZJOI2008]树的统计Count (树链剖分 - 点权剖分 - 单点权修改)

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1036 树链剖分模版题,打的时候注意点就行.做这题的时候,真的傻了,单词拼错检查了一个多小时 ...

  4. 【函数式权值分块】【分块】bzoj3196 Tyvj 1730 二逼平衡树

    #include<cstdio> #include<cmath> #include<algorithm> using namespace std; #define ...

  5. POJ3237 Tree 树链剖分 边权

    POJ3237 Tree 树链剖分 边权 传送门:http://poj.org/problem?id=3237 题意: n个点的,n-1条边 修改单边边权 将a->b的边权取反 查询a-> ...

  6. POJ2763 Housewife Wind 树链剖分 边权

    POJ2763 Housewife Wind 树链剖分 边权 传送门:http://poj.org/problem?id=2763 题意: n个点的,n-1条边,有边权 修改单边边权 询问 输出 当前 ...

  7. HDU3669 Aragorn's Story 树链剖分 点权

    HDU3669 Aragorn's Story 树链剖分 点权 传送门:http://acm.hdu.edu.cn/showproblem.php?pid=3966 题意: n个点的,m条边,每个点都 ...

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

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

  9. POJ 3237.Tree -树链剖分(边权)(边值更新、路径边权最值、区间标记)贴个板子备忘

    Tree Time Limit: 5000MS   Memory Limit: 131072K Total Submissions: 12247   Accepted: 3151 Descriptio ...

随机推荐

  1. 运动目标前景检测之ViBe源代码分析

    一方面为了学习,一方面按照老师和项目的要求接触到了前景提取的相关知识,具体的方法有很多,帧差.背景减除(GMM.CodeBook. SOBS. SACON. VIBE. W4.多帧平均……).光流(稀 ...

  2. ionic运行测试

    http://blog.csdn.net/yucihan/article/details/54631747

  3. Good Substrings CodeForces - 271D

    You've got string s, consisting of small English letters. Some of the English letters are good, the ...

  4. HLPP

    LOJ 最大流加强版 #include <bits/stdc++.h> const int inf=0x7fffffff; const int maxn=1210; const int m ...

  5. Google MapReduce中文版

    英文原文链接: Google Map Reduce 译文原文链接: Google MapReduce中文版 Google MapReduce中文版 译者: alex 摘要 MapReduce是一个编程 ...

  6. 在Maven中怎么配置外部Jar

    转摘自:http://liugang594.iteye.com/blog/1677712 假设我们有一个Maven的project,其中有些Jar包不是来自Maven库的,是存在本地的某些Jar文件, ...

  7. 数据结构之DFS与BFS

    深度搜索(DFS) and  广度搜索(BFS) 代码如下: #include "stdafx.h" #include<iostream> #include<st ...

  8. 【bzoj3510】首都 LCT维护子树信息(+启发式合并)

    题目描述 在X星球上有N个国家,每个国家占据着X星球的一座城市.由于国家之间是敌对关系,所以不同国家的两个城市是不会有公路相连的. X星球上战乱频发,如果A国打败了B国,那么B国将永远从这个星球消失, ...

  9. MongoDB简介以及下载安装

    什么是MongoDB ? MongoDB 是由C++语言编写的,是一个基于分布式文件存储的开源数据库系统.运行稳定,性能高 在高负载的情况下,添加更多的节点,可以保证服务器性能. MongoDB 旨在 ...

  10. 网络知识===cookie 、session、JSESSIONID的区别

    cookie .session ? 让我们用几个例子来描述一下cookie和session机制之间的区别与联系.笔者曾经常去的一家咖啡店有喝5杯咖啡免费赠一杯咖啡的优惠,然而一次性消费5杯咖啡的机会微 ...