[CTSC2008]网络管理

题目描述

M 公司是一个非常庞大的跨国公司,在许多国家都设有它的下属分支机构或部门。为了让分布在世界各地的 n n n 个部门之间协同工作,公司搭建了一个连接整个公司的通信网络。

该网络的结构由 n n n 个路由器和 n − 1 n-1 n1 条高速光缆组成。每个部门都有一个专属的路由器,部门局域网内的所有机器都联向这个路由器,然后再通过这个通信子网与其他部门进行通信联络。该网络结构保证网络中的任意两个路由器之间都存在一条直接或间接路径以进行通信。

高速光缆的数据传输速度非常快,以至于利用光缆传输的延迟时间可以忽略。但是由于路由器老化,在这些路由器上进行数据交换会带来很大的延迟。而两个路由器之间的通信延迟时间则与这两个路由器通信路径上所有路由器中最大的交换延迟时间有关。

作为 M 公司网络部门的一名实习员工,现在要求你编写一个简单的程序来监视公司的网络状况。该程序能够随时更新网络状况的变化信息(路由器数据交换延迟时间的变化),并且根据询问给出两个路由器通信路径上延迟第 k k k 大的路由器的延迟时间。


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

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

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

输入格式

第一行为两个整数 n n n q q q,分别表示路由器总数和询问的总数。

第二行有 n n n 个整数,第 i i i 个数表示编号为i的路由器初始的数据延迟时间 t i t_i ti

紧接着 n − 1 n-1 n1 行,每行包含两个整数 x x x y y y。表示有一条光缆连接路由器 x x x 和路由器 y y y

紧接着是 q q q 行,每行三个整数 k , a , b k,a,b k,a,b

如果 k = 0 k=0 k=0,则表示路由器 a a a 的状态发生了变化,它的数据交换延迟时间由 t a t_a ta 变为 b b b

如果 k > 0 k>0 k>0,则表示询问 a a a b b b 的路径上所经过的所有路由器(包括 a a a b b b)中延迟第 k k k 大的路由器的延迟时间。注意 a a a 可以等于 b b b,此时路径上只有一个路由器。

输出格式

对于每一个第二种询问(即 k > 0 k>0 k>0 ),输出一行。
包含一个整数为相应的延迟时间。如果路径上的路由器不足 k k k 个,则输出信息 invalid request!

样例 #1

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

提示

【数据范围】
对于 100 % 100\% 100% 的数据, 1 ≤ n , q ≤ 80000 1\le n,q \le 80000 1n,q80000 0 ≤ k ≤ n 0 \le k \le n 0kn,任意一个路由器在任何时刻都满足延迟时间小于 1 0 8 10^8 108

题目思路

树上待修莫队,码量较大,调试时仔细一些,变量名不要搞混。

Code

#include
using namespace std;
int n,m,a[600000+10],val[600000+10],cnt[600000+10],sum[600000+10],st[600000+10],ed[600000+10],c[600000+10][2],fans[600000+10],totsiz=0,tim=0,block=0;
int head[600000+10],nxt[600000+10],to[600000+10],siz[600000+10],fa[600000+10],dep[600000+10],son[600000+10],top[600000+10],tot=0,totcnt=0;
int b[600000+10],cal[600000+10],mp[600000+10],sizs=0;
struct node
{
    int l,r,k,t,id,lca;
}q[600000+10];
void add(int u,int v)
{
    to[++tot]=v;
    nxt[tot]=head[u];
    head[u]=tot;
}
int read()
{
    int s=0,w=1;
    char ch=getchar();
    while(ch<'0'||ch>'9')
    {
        if(ch=='-')
            w=-1;
        ch=getchar();
    }
    while(ch>='0'&&ch<='9')
        s=s*10+(ch-'0'),ch=getchar();
    return s*w;
}
void dfs1(int u,int f)
{
    a[++totsiz]=u;
    st[u]=totsiz;
    fa[u]=f;
    dep[u]=dep[f]+1;
    siz[u]=1;
    for(int i=head[u];i;i=nxt[i])
    {
        int v=to[i];
        if(v==f)
            continue;
        dfs1(v,u);
        if(siz[son[u]]<siz[son[v]])
            son[u]=v;
    }
    a[++totsiz]=u;
    ed[u]=totsiz;
}
void dfs2(int u,int f)
{
    top[u]=f;
    if(son[u])
        dfs2(son[u],f);
    for(int i=head[u];i;i=nxt[i])
    {
        int v=to[i];
        if(v!=fa[u]&&v!=son[u]) 
            dfs2(v,v);    
    }
}
int lca(int x,int y)
{
    while(top[x]!=top[y])
    {
        if(dep[top[x]]<dep[top[y]])
            swap(x,y);
        x=fa[top[x]];
    }
    if(dep[x]>dep[y])
        swap(x,y);
    return x;
}
bool cmp(node a,node b)
{
    if(a.l/block!=b.l/block)
        return a.l<b.l;
    if(a.r/block!=b.r/block)
    {
        if((a.l/block)&1) 
            return a.r<b.r;
		else
            return a.r>b.r;
    }
    if((a.r/block)&1) 
        return a.t<b.t;
    else
        return a.t>b.t;
}
void add(int x)
{
    cnt[x]++;
    sum[(x-1)/block]++;
}
void del(int x)
{
    cnt[x]--;
    sum[(x-1)/block]--;
}
void gs(int x)
{
    cal[x]^=1;
    if(cal[x])
        add(val[x]);
    else
        del(val[x]);
}
void change(int t)
{
    if(cal[c[t][0]])
    {
        gs(c[t][0]);
        swap(val[c[t][0]],c[t][1]);
        gs(c[t][0]);
    }
    else
        swap(val[c[t][0]],c[t][1]);
}
int work(int k)
{
    int i=0;
    for(i=300;i>=0;--i)
    {
        if(k>sum[i])
            k-=sum[i];
        else
            break;
    }
    for(int j=(i+1)*block;j>=i*block+1;--j)
    {
        if(cnt[j]>=k)
            return j;
        else    
            k-=cnt[j];
    }
    return -1;
}
int main()
{
    n=read(),m=read();
    block=pow(n,0.6666);
    for(int i=1;i<=n;++i)
        val[i]=read(),b[++sizs]=val[i];
    for(int i=1;i<=n-1;++i)
    {
        int x=read(),y=read();
        add(x,y);
        add(y,x);
    }
    dfs1(1,1);
    dfs2(1,1);
    for(int i=1;i<=m;++i)
    {   
        int k=read(),x=read(),y=read();
        if(k==0)
        {
            tim++;
            c[tim][0]=x;
            c[tim][1]=y;
            b[++sizs]=c[tim][1];
        }
        else
        {
            totcnt++;
            if(st[x]>st[y])
                swap(x,y);
            q[totcnt].lca=lca(x,y);
            q[totcnt].k=k;
            q[totcnt].id=totcnt;
            q[totcnt].t=tim;
            if(q[totcnt].lca==x)
            {
                q[totcnt].lca=0;
                q[totcnt].l=st[x];
                q[totcnt].r=st[y];
            }
            else
            {   
                q[totcnt].l=ed[x];
                q[totcnt].r=st[y];
            }
        }
    } 
    sort(b+1,b+sizs+1);
    sizs=unique(b+1,b+sizs+1)-b-1;
    for(int i=1;i<=n;++i)
    {
        int v=val[i];
        val[i]=lower_bound(b+1,b+sizs+1,val[i])-b;
        mp[val[i]]=v;
        // cout<
    }
    for(int i=1;i<=tim;++i)
    {
        int v=c[i][1];
        c[i][1]=lower_bound(b+1,b+sizs+1,c[i][1])-b; 
        mp[c[i][1]]=v;
    }
    // for(int i=1;i<=totcnt;++i)
    //     cout<
    sort(q+1,q+totcnt+1,cmp);
    int l=1,r=0,t=0;
    for(int i=1;i<=totcnt;++i)
    {
        while(l>q[i].l)
            gs(a[--l]);
        while(r<q[i].r)
            gs(a[++r]);
        while(l<q[i].l)
            gs(a[l++]);
        while(r>q[i].r) 
            gs(a[r--]);
        while(t<q[i].t)
            change(++t);
        while(t>q[i].t)
            change(t--);
        if(q[i].lca)
            gs(q[i].lca);
        fans[q[i].id]=work(q[i].k);
        if(q[i].lca)
            gs(q[i].lca);
    }
    for(int i=1;i<=totcnt;++i)
    {
        if(fans[i]==-1)
            printf("invalid request!\n");
        else
            printf("%d\n",mp[fans[i]]);
    }
    return 0;
}

你可能感兴趣的:(c++,数据结构)