裸题,直接上。复杂度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. [CF816E] Karen and Supermarket1 [树形dp]

    传送门 - > \(CF816E\) Karen and Supermarket 题意翻译 在回家的路上,凯伦决定到超市停下来买一些杂货. 她需要买很多东西,但因为她是学生,所以她的预算仍然很有 ...

  2. linux下将jpg,jpeg格式转为PDF

    1.安装imagemagick(用其中的convert)和gthumb     sudo apt-get install imagemagick gthumb 2.将tiff图片转换为png或jpeg ...

  3. 九大排序算法Java实现

    之前学习数据结构与算法时花了三天时间整理九大排序算法,并采用Java语言来实现,今天第一次写博客,刚好可以把这些东西从总结的文档中拿出来与大家分享一下,同时作为自己以后的备忘录. 1.排序算法时间复杂 ...

  4. Python基础(4)_集合、布尔类型

    一.集合 集合的作用一:关系运算集合的作用二:去重 定义集合:集合内的元素必须是唯一的:集合内的元素必须是可hash的,也是就不可变类型:集合是无序的 s={'egon',123,'egon','1' ...

  5. bootstrap-datetimepicker年视图中endDate设置之后比正常时间提前两个月

    问题 bootstrap-datetimepicker年视图中endDate设置结束时间为2016-08,(即8月之后的日期不能选)而在日历上显示时为2016-06,相差两个月,即6月之后的日期不能选 ...

  6. eclipse使用git下载项目

    准备工作: 目的:从远程仓库github上down所需的项目 eclipse使用Git插件下载github上项目 eclipse版本:eclipse4.5  64位 jdk版本:jdk-1.7 64位 ...

  7. camera驱动框架分析(中)

    camera host的驱动 下面开始分析camera host吧,如果仅仅是想知道camera sensor驱动怎么写,而不想知道内部具体怎么个调用流程,怎么个架构设计,那可以跳过该部分,直接去看i ...

  8. 51nod 几道题

    1001 数组中和等于K的数对 基准时间限制:1 秒 空间限制:131072 KB 分值: 5 难度:1级算法题 给出一个整数K和一个无序数组A,A的元素为N个互不相同的整数, 找出数组A中所有和等于 ...

  9. selenium 3.0 键盘事件 +强制结束chromedriver进程代码

    selenium自动化测试常常用到键盘操作,一下是键盘操作的详细操作,和部分代码.截图来自于虫师的自动化相关书籍. public static void main(String[] args) thr ...

  10. mysql:functional dependency

    0down vote First, a functional dependency in the form A->B means that, given one value for A, we ...