BZOJ 1146 [CTSC2008] 网络管理Network 主席树

本文介绍了一种利用树剖和LCA算法解决网络监控问题的方法,通过维护树上路径,实现对路由器延迟时间的有效更新与查询。采用主席树和树状数组优化算法效率。

题目描述 Description
M公司是一个非常庞大的跨国公司,在许多国家都设有它的下属分支机构或部门.为了让分布在世界各地的N个
部门之间协同工作,公司搭建了一个连接整个公司的通信网络.该网络的结构由N个路由器和N-1条高速光缆组成.
每个部门都有一个专属的路由器,部门局域网内的所有机器都联向这个路由器,然后再通过这个通信子网与其他部
门进行通信联络.该网络结构保证网络中的任意两个路由器之间都存在一条直接或间接路径以进行通信.
高速光缆的数据传输速度非常快,以至于利用光缆传输的延迟时间可以忽略.但是由于路由器老化,在这些路由器上进行
数据交换会带来很大的延迟.而两个路由器之间的通信延迟时间则与这两个路由器通信路径上所有路由器中最大的
交换延迟时间有关.作为M公司网络部门的一名实习员工,现在要求你编写一个简单的程序来监视公司的网络状况
.该程序能够随时更新网络状况的变化信息(路由器数据交换延迟时间的变化),并且根据询问给出两个路由器通
信路径上延迟第k大的路由器的延迟时间.
【任务】你的程序从输入文件中读入N个路由器和N-1条光缆的连接信息,每个路由器初始的数据交换延迟时间Ti,以及Q条询问(或状态改变)的信息.并依次处理这Q条询问信息,它们可能是:
1. 由于更新了设备,或者设备出现新的故障,使得某个路由器的数据交换延迟时间发生了变化
2. 查询某两个路由器a和b之间的路径上延迟第k大的路由器的延迟时间

输入描述 Input Description
第一行为两个整数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大的路由器的延迟时间

输出描述 Output Description
对于每一个第二种询问(k>0),输出一行,包含一个整数,为相应的延迟时间
如果路径上的路由器不足k个,则输出信息“invalid request!”
(全部小写不包含引号,两个单词之间有一个空格)

样例输入 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!

数据范围及提示 Data Size & Hint
N,Q<=80000,任意一个路由器在任何时刻都满足延迟时间小于10^8
对于所有询问满足0<=K<=N

Solution

首先要完成这道题,需要会维护树上路径的方法
最常用的就是树剖&LCA
这道题我们利用LCA前缀和的性质来进行路径维护

u->v的一条路径可以看做road(root,u)+road(root,v)-road(LCA(u,v))-road(fa[LCA(u,v)])
这样的形式就很好维护了

用主席树来维护一下每个点到根节点所有权值
但是有修改操作怎么办?

利用一下BZOJ 1901 Zju2112 Dynamic Rankings的方法树状数组套主席树来修改

这里每次修改一个点对于它的子树中所有的节点都有贡献
所以要将子树中所有节点都修改
显然直接修改不行
那么使用dfs序,保证每个点的子树都在一个特定的区间[dfnl[x],dfnr[x]]内,所以直接区间修改

但是原方案只能单点修改
对树状数组比较熟悉的就知道树状数组来维护差分数列来做到区间修改单点查询
这样就非常爽了
(搞了好久没搞出来QwQ)

这样就能A掉这道题了

#include <bits/stdc++.h>
using namespace std;
const int N=80005;
struct T {
    int sum,l,r;
    T(){}
    T(int _sum,int _l,int _r) {sum=_sum;l=_l;r=_r;}
}t[10000010];
int rt[N],cnt;
struct edge {
    int t,n;
}e[N<<1];
int head[N],tot;
int n,q;
int DFN,dfnl[N],dfnr[N],deep[N],fa[N][20];
int a[N],num[N<<1],NUM;
int A[N],B[N],K[N];
int L[N],R[N],u,v;
int read() {
    int ans=0,flag=1;
    char ch=getchar();
    while((ch>'9' || ch<'0') && ch!='-') ch=getchar();
    if(ch=='-') {flag=-1,ch=getchar();}
    while(ch>='0' && ch<='9') {ans=ans*10+ch-'0';ch=getchar();}
    return ans*flag;
}
inline int lowbit(int x) {return x&(-x);}
inline void addedge(int x,int y) {
    ++tot;
    e[tot].t=y;
    e[tot].n=head[x];
    head[x]=tot;
}
inline void insert(int &rt,int pos,int l,int r,int x) {
    if(!rt) rt=++cnt;
    t[rt].sum+=x;
    if(l==r) return;
    int mid=(l+r)>>1;
    if(pos<=mid) insert(t[rt].l,pos,l,mid,x);
    else insert(t[rt].r,pos,mid+1,r,x);
}
int query(int l,int r,int k) {
    if(l==r) return l;
    int s=0;
    for(int i=1;i<=u;i++) s-=t[t[L[i]].l].sum;
    for(int i=1;i<=v;i++) s+=t[t[R[i]].l].sum;
    int mid=(l+r)>>1;
    if(s>=k) {
        for(int i=1;i<=u;i++) L[i]=t[L[i]].l;
        for(int i=1;i<=v;i++) R[i]=t[R[i]].l;
        return query(l,mid,k);
    }
    else {
        for(int i=1;i<=u;i++) L[i]=t[L[i]].r;
        for(int i=1;i<=v;i++) R[i]=t[R[i]].r;
        return query(mid+1,r,k-s);
    }
}
void dfs(int x) {
    dfnl[x]=++DFN;
    deep[x]=deep[fa[x][0]]+1;
    for(int i=1;i<20;i++) fa[x][i]=fa[fa[x][i-1]][i-1];
    for(int i=head[x];i;i=e[i].n) {
        if(e[i].t==fa[x][0]) continue;
        fa[e[i].t][0]=x;
        dfs(e[i].t);
    }
    dfnr[x]=DFN;
    for(int i=dfnl[x];i<=n;i+=lowbit(i))
        insert(rt[i],a[x],1,NUM,1);
    for(int i=dfnr[x]+1;i<=n;i+=lowbit(i))
        insert(rt[i],a[x],1,NUM,-1);
}
int getlca(int x,int y) {
    if(deep[x]<deep[y]) swap(x,y);
    for(int i=19;~i;i--)
        if(deep[fa[x][i]]>=deep[y])
            x=fa[x][i];
    if(x==y) return x;
    for(int i=19;~i;i--)
        if(fa[x][i]!=fa[y][i]) {
            x=fa[x][i];
            y=fa[y][i];
        }
    return fa[x][0];
}
int main() {
    n=read();q=read();
    for(int i=1;i<=n;i++) {
        a[i]=read();
        num[++NUM]=a[i];
    }
    for(int i=1;i<n;i++) {
        int x=read(),y=read();
        addedge(x,y);addedge(y,x);
    }
    for(int i=1;i<=q;i++) {
        K[i]=read();A[i]=read();B[i]=read();
        if(K[i]==0) num[++NUM]=B[i];
    }
    sort(num+1,num+NUM+1);
    NUM=unique(num+1,num+NUM+1)-(num+1);
    for(int i=1;i<=n;i++)
        a[i]=lower_bound(num+1,num+NUM+1,a[i])-num;
    dfs(1);
    for(int i=1;i<=q;i++) {
        int x=A[i],y=B[i],k=K[i];
        if(k) {
            u=v=0;
            int lca=getlca(x,y),flca=fa[lca][0];
            int s=deep[x]+deep[y]-deep[lca]-deep[flca];
            if(k>s) {puts("invalid request!");continue;}
            for(int i=dfnl[x];i;i-=lowbit(i)) R[++v]=rt[i];
            for(int i=dfnl[y];i;i-=lowbit(i)) R[++v]=rt[i];
            for(int i=dfnl[lca];i;i-=lowbit(i)) L[++u]=rt[i];
            for(int i=dfnl[flca];i;i-=lowbit(i)) L[++u]=rt[i];
            printf("%d\n",num[query(1,NUM,s-k+1)]);
        }
        else {
            for(int i=dfnl[x];i<=n;i+=lowbit(i))
                insert(rt[i],a[x],1,NUM,-1);
            for(int i=dfnr[x]+1;i<=n;i+=lowbit(i))
                insert(rt[i],a[x],1,NUM,1);
            a[x]=lower_bound(num+1,num+NUM+1,y)-num;
            for(int i=dfnl[x];i<=n;i+=lowbit(i))
                insert(rt[i],a[x],1,NUM,1);
            for(int i=dfnr[x]+1;i<=n;i+=lowbit(i))
                insert(rt[i],a[x],1,NUM,-1);
        }
    }
    return 0;
}
【3D应力敏感度分析拓扑优化】【基于p-范数全局应力衡量的3D敏感度分析】基于伴随方法的有限元分析和p-范数应力敏感度分析(Matlab代码实现)内容概要:本文档介绍了基于伴随方法的有限元分析与p-范数全局应力衡量的3D应力敏感度分析,并结合拓扑优化技术,提供了完整的Matlab代码实现方案。该方法通过有限元建模计算结构在载荷作用下的应力分布,采用p-范数对全局应力进行有效聚合,避免传统方法中应力约束过多的问题,进而利用伴随法高效求解设计变量对应力的敏感度,为结构优化提供关键梯度信息。整个流程涵盖了从有限元分析、应力评估到敏感度计算的核心环节,适用于复杂三维结构的轻量化与高强度设计。; 适合人群:具备有限元分析基础、拓扑优化背景及Matlab编程能力的研究生、科研人员与工程技术人员,尤其适合从事结构设计、力学仿真与多学科优化的相关从业者; 使用场景及目标:①用于实现高精度三维结构的应力约束拓扑优化;②帮助理解伴随法在敏感度分析中的应用原理与编程实现;③服务于科研复现、论文写作与工程项目中的结构性能提升需求; 阅读建议:建议读者结合有限元理论与优化算法知识,逐步调试Matlab代码,重点关注伴随方程的构建与p-范数的数值处理技巧,以深入掌握方法本质并实现个性化拓展。
下载前必看:https://pan.quark.cn/s/9f13b242f4b9 Android 平板设备远程操控个人计算机的指南 Android 平板设备远程操控个人计算机的指南详细阐述了如何运用 Splashtop Remote 应用程序达成 Android 平板设备对个人计算机的远程操控。 该指南被划分为四个环节:首先,在个人计算机上获取并部署 Splashtop Remote 应用程序,并设定客户端密码;其次,在 Android 平板设备上获取并部署 Splashtop Remote 应用程序,并与之建立连接至个人计算机的通道;再次,在 Splashtop Remote 应用程序中识别已部署个人计算机端软件的设备;最后,运用平板设备对个人计算机实施远程操控。 关键点1:Splashtop Remote 应用程序的部署与配置* 在个人计算机上获取并部署 Splashtop Remote 应用程序,可通过官方网站或其他获取途径进行下载。 * 部署结束后,必须输入客户端密码,该密码在平板控制计算机时用作验证,密码长度至少为8个字符,且需包含字母与数字。 * 在配置选项中,能够设定是否在设备启动时自动运行客户端,以及进行互联网搜索设置。 关键点2:Splashtop Remote 应用程序的 Android 版本获取与部署* 在 Android 平板设备上获取并部署 Splashtop Remote 应用程序,可通过 Google Play Store 或其他获取途径进行下载。 * 部署结束后,必须输入客户端密码,该密码用于连接至个人计算机端软件。 关键点3:运用 Splashtop Remote 远程操控个人计算机* 在 Splashtop Remote 应用程序中识别...
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值