• [CTSC2008]网络管理


    题目描述

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

    【任务】 你的程序从输入文件中读入N个路由器和N-1条光缆的连接信息,每个路由器初始的数据交换延迟时间Ti,以及Q条询问(或状态改变)的信息。并依次处理这Q条询问信息,它们可能是:

    1. 由于更新了设备,或者设备出现新的故障,使得某个路由器的数据交换延迟时间发生了变化。

    2. 查询某两个路由器a和b之间的路径上延迟第k大的路由器的延迟时间。

    输入输出格式

    输入格式:

    第一行为两个整数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大的路由器的延迟时间。注意a可以等于b,此时路径上只有一个路由器。

    输出格式:

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

    输入输出样例

    输入样例#1: 复制
    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
    输出样例#1: 复制
    3
    2
    2
    invalid request!

    说明

    测试数据满足N,Q<=80000,任意一个路由器在任何时刻都满足延迟时间小于10^8。对于所有询问满足0<=K<=N 。

    将原树按dfs序标号

    然后按照从父亲到儿子建主席树

    查询(x,y)就是这样:

    令w=lca(x,y),h=fa(w)

    对于一个数对应4颗树(x,y,w,h)的节点(r1,r2,r3,r4),如果满足

    $c[rt1]+c[rt2]-c[rt3]-c[rt4]==k$那么就是答案

    但是修改一个点最多要更新n颗线段树

    所以用树状数组维护主席树

    所以查询时,要把查询(x,y,w,h)涉及到的线段树的根节点编号记下来

    然后二分,还是按主席树求区间k大的套路

    不过要把记下来的所有节点编号全部左移或右移

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cstring>
      4 #include<algorithm>
      5 #include<cmath>
      6 using namespace std;
      7 struct Node
      8 {
      9   int next,to;
     10 }edge[200001];
     11 int num,head[100001],dfn[100001],tot,size[100001],dep[100001],fa[100001][21],pos;
     12 int c[48000005],ch[48000005][2],n,root[100001],N=1e8,k,cnt,t[100001],vis[100001];
     13 int now[100001],sum,q,a[100001],ans;
     14 void add(int u,int v)
     15 {
     16   num++;
     17   edge[num].next=head[u];
     18   head[u]=num;
     19   edge[num].to=v;
     20 }
     21 void dfs(int x,int pa)
     22 {int i;
     23   dfn[x]=++tot;
     24   size[x]=1;
     25   dep[x]=dep[pa]+1;
     26   for (i=1;i<=20;i++)
     27       {
     28     fa[x][i]=fa[fa[x][i-1]][i-1];
     29       }
     30   for (i=head[x];i;i=edge[i].next)
     31     {
     32       int v=edge[i].to;
     33       if (v==pa) continue;
     34       fa[v][0]=x;
     35       dfs(v,x);
     36       size[x]+=size[v];
     37     }
     38 }
     39 int lca(int x,int y)
     40 {int i;
     41   if (dep[x]<dep[y]) swap(x,y);
     42   for (i=20;i>=0;i--)
     43     if ((1<<i)<=dep[x]-dep[y]) x=fa[x][i];
     44   if (x==y) return x;
     45   for (i=20;i>=0;i--)
     46     if (fa[x][i]!=fa[y][i])
     47       {
     48     x=fa[x][i];y=fa[y][i];
     49       }
     50   return fa[x][0];
     51 }
     52 void update(int &rt,int l,int r,int x,int d)
     53 {
     54   if (!rt) rt=++pos;
     55   c[rt]+=d;
     56   if (l==r) return;
     57   int mid=(l+r)/2;
     58   if (x<=mid)
     59   update(ch[rt][0],l,mid,x,d);
     60   else update(ch[rt][1],mid+1,r,x,d);
     61 }
     62 void add(int x,int d,int f)
     63 {
     64   while (x<=n)
     65     {
     66       update(root[x],0,N,d,f);
     67       x+=(x&(-x));
     68     }
     69 }
     70 int query(int x,int y,int w,int h)
     71 {int i;
     72   if (dep[x]-dep[w]+dep[y]-dep[h]<k)
     73     return -1;
     74   k=dep[x]+dep[y]-dep[w]-dep[h]-k+1;
     75   if (k<=0) return -1;
     76   x=dfn[x];y=dfn[y];w=dfn[w];h=dfn[h];
     77   cnt=0;
     78   for (i=x;i;i-=(i&(-i)))
     79     {
     80       if (vis[i]) continue;
     81       t[++cnt]=i;
     82       vis[i]=1;
     83     }
     84     for (i=y;i;i-=(i&(-i)))
     85     {
     86       if (vis[i]) continue;
     87       t[++cnt]=i;
     88       vis[i]=1;
     89     }
     90     for (i=w;i;i-=(i&(-i)))
     91     {
     92       if (vis[i]) continue;
     93       t[++cnt]=i;
     94       vis[i]=1;
     95     }
     96     for (i=h;i;i-=(i&(-i)))
     97     {
     98       if (vis[i]) continue;
     99       t[++cnt]=i;
    100       vis[i]=1;
    101     }
    102     for (i=1;i<=cnt;i++)
    103       now[t[i]]=root[t[i]];
    104     int l=0,r=N;
    105     while (l<r)
    106       {
    107     sum=0;
    108     for (i=x;i;i-=(i&(-i)))
    109       sum+=c[ch[now[i]][0]];
    110     for (i=y;i;i-=(i&(-i)))
    111       sum+=c[ch[now[i]][0]];
    112     for (i=w;i;i-=(i&(-i)))
    113       sum-=c[ch[now[i]][0]];
    114     for (i=h;i;i-=(i&(-i)))
    115       sum-=c[ch[now[i]][0]];
    116     int mid=(l+r)/2;
    117     if (sum<k)
    118       {
    119         k-=sum;l=mid+1;
    120         for (i=1;i<=cnt;i++)
    121           now[t[i]]=ch[now[t[i]]][1];
    122       }
    123     else
    124       {
    125         r=mid;
    126         for (i=1;i<=cnt;i++)
    127           now[t[i]]=ch[now[t[i]]][0];
    128       }
    129       }
    130     for (i=1;i<=cnt;i++)
    131       vis[t[i]]=0;
    132     return l;
    133 }
    134 int main()
    135 {int i,x,y,u,v;
    136   cin>>n>>q;
    137   for (i=1;i<=n;i++)
    138     {
    139       scanf("%d",&a[i]);
    140     }
    141   for (i=1;i<=n-1;i++)
    142     {
    143       scanf("%d%d",&u,&v);
    144       add(u,v);add(v,u);
    145     }
    146   dfs(1,0);
    147   for (i=1;i<=n;i++)
    148     {
    149       add(dfn[i],a[i],1);
    150       add(dfn[i]+size[i],a[i],-1);
    151     }
    152   while (q--)
    153     {
    154       scanf("%d%d%d",&k,&x,&y);
    155       if (k==0)
    156     {
    157       add(dfn[x],a[x],-1);
    158       add(dfn[x]+size[x],a[x],1);
    159       add(dfn[x],y,1);
    160       add(dfn[x]+size[x],y,-1);
    161       a[x]=y;
    162     }
    163       else
    164     {
    165       int w=lca(x,y),h=fa[w][0];
    166       ans=query(x,y,w,h);
    167       if (ans!=-1)
    168         printf("%d
    ",ans);
    169       else
    170         printf("invalid request!
    ");
    171     }
    172     }
    173 }
  • 相关阅读:
    zedGraph画心电图
    多窗体之间进行数据通信 传值
    C#共有五种访问修饰符:public、private、protected、internal、protected internal。作用范围如下表:
    Linux进程调度与切换
    Linux学习总结
    Linux内核如何启动并装载一个可执行程序
    Linux编写Shell脚本入门
    如何使用委托
    深入剖析反射
    浅析C#中的文件操作
  • 原文地址:https://www.cnblogs.com/Y-E-T-I/p/8964205.html
Copyright © 2020-2023  润新知