裸题,直接上。复杂度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. Codeforces Round #350 (Div. 2) A

    A. Holidays time limit per test 1 second memory limit per test 256 megabytes input standard input ou ...

  2. [bzoj 3224]手写treap

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=3224 bzoj不能用time(0),看到这个博客才知道,我也RE了好几发…… #inclu ...

  3. com.mongodb.MongoException$CursorNotFound: cursor not found on server异常处理

    java链接MongoDB处理大量数据时经常碰到cursor not found 的异常,其实是超时所致 Exception in thread "main" com.mongod ...

  4. import pymongo exceptions.ImportError: No module named pymongo

    最近用Scrapy写爬虫,将爬取的数据存入Mongodb中,使用的是pymongo这个库,但是运行的时候报错如标题所示 搜了好多网站包括stackoverflow都没有解决,后来发现自己用的是虚拟环境 ...

  5. js 日期获去及格式化

    原文地址:http://www.cnblogs.com/qinpengming/archive/2012/12/03/2800002.html Js获取当前日期时间及格式化操作 var myDate ...

  6. shell编程 if 注意事项

    read -n 1 -p "Let's go(y or n):" if [ "$REPLY"x = "y"x -o "$REPLY ...

  7. WebView使用--文章集锦

    对于android WebView加载不出Html5网页的解决方法 在android4.4中webview的使用相对于之前版本的一些区别 理解WebKit和Chromium: Android 4.4 ...

  8. C# 序列化理解 1(转)

    序列化又称串行化,是.NET运行时环境用来支持用户定义类型的流化的机制.其目的是以某种存储形成使自定义对象持久化,或者将这种对象从一个地方传输到另一个地方.    .NET框架提供了两种串行化的方式: ...

  9. 计算机网络中七层,五层,四层协议;IP 地址子网划分

    七层协议: 7 应用层(http) 6 表示层(上层用户可以相互识别的数据:jpg) 5 会话层(不同主机不同线程间的通信) 4 运输层(tcp/ip:传输层提供端到端的透明数据服务)/差错控制和流量 ...

  10. compositionstart 、 compositionend 、 input都存在时的解决办法

    $(function () { var cpLock = true; $('#textbox').off().on({ compositionstart: function () {//中文输入开始 ...