• [CTSC2008] 网络管理


    题目描述 Description

    M公司是一个非常庞大的跨国公司,在许多国家都设有它的下属分支机构或部门。为了让分布在世界各地的N个部门之间 协同工作,公司搭建了一个连接整个公司的通信网络。该网络的结构由N个路由器和N-1条高速光缆组成。每个部门都有一个专属的路由器,部门局域网内的所有 机器都联向这个路由器,然后再通过这个通信子网与其他部门进行通信联络。该网络结构保证网络中的任意两个路由器之间都存在一条直接或间接路径以进行通信。

     高速光缆的数据传输速度非常快,以至于利用光缆传输的延迟时间可以忽略。但是由于路由器老化,在这些路由器上进行数据交换会带来很大的延迟。而两 个路由器之间的通信延迟时间则与这两个路由器通信路径上所有路由器中最大的交换延迟时间有关。作为M公司网络部门的一名实习员工,现在要求你编写一个简单 的程序来监视公司的网络状况。该程序能够随时更新网络状况的变化信息(路由器数据交换延迟时间的变化),并且根据询问给出两个路由器通信路径上延迟第k大 的路由器的延迟时间。

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

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

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

    输入描述 Input Description

    输入文件network.in中的第一行为两个整数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,此时路径上只有一个路由器。

    输出描述 Output Description

    输出文件为network.out。对于每一个第二种询问(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

    100% 测试数据满足 n<=80000,q<=30000 。任意一个路由器在任何时刻都满足延迟时间小于108。对于所有询问满足 。

    40% 测试数据满足所有询问中1<=k<=5 ,且路由器的延迟时间不会发生变化。

    10% 测试数据满足n,q<=8000 。

    难得看到一道网管题。。。

    这个题貌似是大佬们一周之前这个时候做的题。。。Orz(更尴尬的是我今天才知道Orz是什么意思)

    我果然是弱,连带修改的主席树都不会。。。

    这个题的大意就是带修改的路径第K大的查询。。。。

    带修改的主席树具体是怎么回事呢???

    本来原本的主席树相当与是一种前缀和主席树,即每个点维护的是[1,i]这个前缀。。。

    如果对这个主席树进行修改的话  需要把后面的主席树全部都修改一遍,所以每次复杂度是 n*logn的。。。加询问的话是n^2logn的。。。萎烂。。。

    带修改的主席树相当于是树状数组套主席树。。。。

    相当于是说每个主席树节点i维护的是对应的树状数组的lowbit(i)的部分的数。。。

    所以每次修改只需要logn*logn的复杂度了。。。

    这种主席树在使用上说更像是值域线段树,跟原来的主席树使用的方法有点差别。。。因为维护的东西不一样了。。。

    大意就是这样的。。。具体实现的话,对每一个节点记一个他原来的的值。。。

    那么修改相当于把这个数删除再加入,即对应insert的时候值域的flag是-1还是1。。。。

    对于这个题来说,在跳lca的时候u--v的路径被分为logn个区间,对于路径上的第k大来说,相当于是二分一个值,转为判断看这log个区间中小于等于这个值的数量有多少。。。

    这个话用主席树实现即可。。。。

    这个是n*logn^4的。。。。

      1 // MADE BY QT666
      2 #include<cstdio>
      3 #include<algorithm>
      4 #include<cmath>
      5 #include<iostream>
      6 #include<queue>
      7 #include<set>
      8 #include<cstdlib>
      9 #include<cstring>
     10 #include<string>
     11 #include<ctime>
     12 #define lson num<<1
     13 #define rson num<<1|1
     14 using namespace std;
     15 typedef long long ll;
     16 const int N=100050;
     17 int gi()
     18 {
     19   int x=0,flag=1;
     20   char ch=getchar();
     21   while(ch<'0'||ch>'9'){if(ch=='-') flag=-1;ch=getchar();}
     22   while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
     23   return x*flag;
     24 }
     25 int fa[N],size[N],top[N],son[N],dep[N],root[N*200],dfn[N],ls[N*200],rs[N*200],last[N],hsh[N*3],w[N],a[N];
     26 int head[N*3],to[N*3],nxt[N*3],tt,cnt,tot,cnt2,sz,s[N*200],n,m,L[N*2],R[N*2],tot1;
     27 struct ac
     28 {
     29   int k,a,b;
     30 }q[N];
     31 void lnk(int x,int y){
     32   to[++cnt]=y,nxt[cnt]=head[x],head[x]=cnt;
     33   to[++cnt]=x,nxt[cnt]=head[y],head[y]=cnt;
     34 }
     35 void dfs1(int x,int f){
     36   dep[x]=dep[f]+1;size[x]=1;
     37   for(int i=head[x];i;i=nxt[i])
     38     {
     39       int y=to[i];
     40       if(y!=f)
     41     {
     42       dfs1(y,x);
     43       fa[y]=x;size[x]+=size[y];
     44       if(size[y]>=size[son[x]]) son[x]=y;
     45     }
     46     }
     47 }
     48 void dfs2(int x,int f)
     49 {
     50   dfn[x]=++tt,top[x]=f;w[tt]=a[x];
     51   if(son[x]) dfs2(son[x],f);
     52   for(int i=head[x];i;i=nxt[i])
     53     {
     54       int y=to[i];
     55       if(y!=fa[x]&&y!=son[x]) dfs2(y,y);
     56     }
     57 }
     58 int lca(int x,int y){
     59   while(top[x]!=top[y]){
     60     if(dep[top[x]]<dep[top[y]]) swap(x,y);
     61     x=fa[top[x]];
     62   }
     63   if(dep[x]<dep[y]) swap(x,y);
     64   return y;
     65 }
     66 void insert(int l,int r,int x,int &y,int v,int flag){
     67   y=++sz;s[y]=s[x]+flag;
     68   ls[y]=ls[x];rs[y]=rs[x];
     69   if(l==r) return;
     70   int mid=(l+r)>>1;
     71   if(v<=mid) insert(l,mid,ls[x],ls[y],v,flag);
     72   else insert(mid+1,r,rs[x],rs[y],v,flag);
     73 }
     74 int query(int l,int r,int x,int k){
     75   int mid=(l+r)>>1;
     76   if(l==r) return 0;
     77   if(k<=mid) return query(l,mid,ls[x],k)+s[rs[x]];
     78   else return query(mid+1,r,rs[x],k);
     79 }
     80 void modify(int x,int v,int flag){
     81   for(;x<=n;x+=(x&-x)) insert(1,tot,root[x],root[x],v,flag);
     82 }
     83 void change(int x,int v){
     84   modify(dfn[x],last[dfn[x]],-1),modify(dfn[x],v,1),last[dfn[x]]=v;
     85 }
     86 int query2(int x,int k){
     87   int ret=0;
     88   for(;x;x-=(x&-x)) ret+=query(1,tot,root[x],k);
     89   return ret;
     90 }
     91 bool check(int k,int K){
     92   int ret=0;
     93   for(int i=1;i<=tot1;i++) ret+=query2(R[i],K)-query2(L[i],K);
     94   return ret<k;
     95 }
     96 int work(int x,int y,int k){
     97   tot1=0;
     98   while(top[x]!=top[y])
     99     {
    100       if(dep[top[x]]<dep[top[y]]) swap(x,y);
    101       L[++tot1]=dfn[top[x]]-1,R[tot1]=dfn[x];
    102       x=fa[top[x]];
    103     }
    104   if(dep[x]<dep[y]) swap(x,y);
    105   L[++tot1]=dfn[y]-1,R[tot1]=dfn[x];
    106   int l=1,r=tot,ans;
    107   while(l<=r)
    108     {
    109       int mid=(l+r)>>1;
    110       if(check(k,mid)) ans=mid,r=mid-1;
    111       else l=mid+1;
    112     }
    113     return hsh[ans];
    114 }
    115 int main()
    116 {
    117   //freopen("1.in","r",stdin);
    118   //freopen("1.out","w",stdout);
    119   n=gi(),m=gi();int u,v;
    120   for (int i=1;i<=n;i++) hsh[++tot]=a[i]=gi();
    121   for (int i=1;i<n;i++) u=gi(),v=gi(),lnk(u,v);
    122   dfs1(1,0),dfs2(1,1);
    123   for (int i=1;i<=m;i++){
    124     q[i].k=gi(),q[i].a=gi(),q[i].b=gi();
    125     if (!q[i].k) hsh[++tot]=q[i].b;
    126   }
    127   sort(hsh+1,hsh+tot+1),tot=unique(hsh+1,hsh+tot+1)-hsh-1;
    128   for (int i=1;i<=n;i++){
    129     w[i]=lower_bound(hsh+1,hsh+tot+1,w[i])-hsh;}
    130   for(int i=1;i<=n;i++) {
    131     modify(i,w[i],1);last[i]=w[i];
    132   }
    133   for (int i=1;i<=m;i++){
    134     if (!q[i].k) q[i].b=lower_bound(hsh+1,hsh+tot+1,q[i].b)-hsh,change(q[i].a,q[i].b); 
    135     else{
    136       if (dep[q[i].a]+dep[q[i].b]-2*dep[lca(q[i].a,q[i].b)]+1<q[i].k) printf("invalid request!
    ");
    137       else printf("%d
    ",work(q[i].a,q[i].b,q[i].k));
    138        }
    139   }
    140   return 0;
    141 }
  • 相关阅读:
    刷题记录:[ByteCTF 2019]EZCMS
    angularJS——自定义指令
    HTML5——语音输入
    jQuery表单验证插件——jquery.validate.js
    纯CSS气泡效果
    管理Cookie的插件——jquery.cookie.js
    网页打印
    CSS hack
    如何挑选适合的前端框架(去哪儿网前端架构师司徒正美)
    让DIV水平和垂直居中的几种方法
  • 原文地址:https://www.cnblogs.com/qt666/p/6505693.html
Copyright © 2020-2023  润新知