【树链剖分】【函数式权值分块】bzoj1146 [CTSC2008]网络管理Network
裸题,直接上。复杂度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的更多相关文章
- 刷题总结——骑士的旅行(bzoj4336 树链剖分套权值线段树)
题目: Description 在一片古老的土地上,有一个繁荣的文明. 这片大地几乎被森林覆盖,有N座城坐落其中.巧合的是,这N座城由恰好N-1条双 向道路连接起来,使得任意两座城都是连通的.也就是说 ...
- 计蒜客 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 ...
- BZOJ 1036 [ZJOI2008]树的统计Count (树链剖分 - 点权剖分 - 单点权修改)
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1036 树链剖分模版题,打的时候注意点就行.做这题的时候,真的傻了,单词拼错检查了一个多小时 ...
- 【函数式权值分块】【分块】bzoj3196 Tyvj 1730 二逼平衡树
#include<cstdio> #include<cmath> #include<algorithm> using namespace std; #define ...
- POJ3237 Tree 树链剖分 边权
POJ3237 Tree 树链剖分 边权 传送门:http://poj.org/problem?id=3237 题意: n个点的,n-1条边 修改单边边权 将a->b的边权取反 查询a-> ...
- POJ2763 Housewife Wind 树链剖分 边权
POJ2763 Housewife Wind 树链剖分 边权 传送门:http://poj.org/problem?id=2763 题意: n个点的,n-1条边,有边权 修改单边边权 询问 输出 当前 ...
- HDU3669 Aragorn's Story 树链剖分 点权
HDU3669 Aragorn's Story 树链剖分 点权 传送门:http://acm.hdu.edu.cn/showproblem.php?pid=3966 题意: n个点的,m条边,每个点都 ...
- [BZOJ1146][CTSC2008]网络管理Network
[BZOJ1146][CTSC2008]网络管理Network 试题描述 M公司是一个非常庞大的跨国公司,在许多国家都设有它的下属分支机构或部门.为了让分布在世界各地的N个 部门之间协同工作,公司搭建 ...
- POJ 3237.Tree -树链剖分(边权)(边值更新、路径边权最值、区间标记)贴个板子备忘
Tree Time Limit: 5000MS Memory Limit: 131072K Total Submissions: 12247 Accepted: 3151 Descriptio ...
随机推荐
- Codeforces Round #350 (Div. 2) A
A. Holidays time limit per test 1 second memory limit per test 256 megabytes input standard input ou ...
- [bzoj 3224]手写treap
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=3224 bzoj不能用time(0),看到这个博客才知道,我也RE了好几发…… #inclu ...
- com.mongodb.MongoException$CursorNotFound: cursor not found on server异常处理
java链接MongoDB处理大量数据时经常碰到cursor not found 的异常,其实是超时所致 Exception in thread "main" com.mongod ...
- import pymongo exceptions.ImportError: No module named pymongo
最近用Scrapy写爬虫,将爬取的数据存入Mongodb中,使用的是pymongo这个库,但是运行的时候报错如标题所示 搜了好多网站包括stackoverflow都没有解决,后来发现自己用的是虚拟环境 ...
- js 日期获去及格式化
原文地址:http://www.cnblogs.com/qinpengming/archive/2012/12/03/2800002.html Js获取当前日期时间及格式化操作 var myDate ...
- shell编程 if 注意事项
read -n 1 -p "Let's go(y or n):" if [ "$REPLY"x = "y"x -o "$REPLY ...
- WebView使用--文章集锦
对于android WebView加载不出Html5网页的解决方法 在android4.4中webview的使用相对于之前版本的一些区别 理解WebKit和Chromium: Android 4.4 ...
- C# 序列化理解 1(转)
序列化又称串行化,是.NET运行时环境用来支持用户定义类型的流化的机制.其目的是以某种存储形成使自定义对象持久化,或者将这种对象从一个地方传输到另一个地方. .NET框架提供了两种串行化的方式: ...
- 计算机网络中七层,五层,四层协议;IP 地址子网划分
七层协议: 7 应用层(http) 6 表示层(上层用户可以相互识别的数据:jpg) 5 会话层(不同主机不同线程间的通信) 4 运输层(tcp/ip:传输层提供端到端的透明数据服务)/差错控制和流量 ...
- compositionstart 、 compositionend 、 input都存在时的解决办法
$(function () { var cpLock = true; $('#textbox').off().on({ compositionstart: function () {//中文输入开始 ...