BZOJ1146: [CTSC2008]网络管理Network

题解:查询带修树链上的第K大 我们可以树链剖分后 用主席树+树状数组维护序列即可 空间(nlog^2n) 时间(nlog^2n)

/**************************************************************
    Problem: 1146
    User: c20161007
    Language: C++
    Result: Accepted
    Time:5264 ms
    Memory:202320 kb
****************************************************************/
 
#include <algorithm>
#include <iostream>
#include <vector>
#include <cstdio>
const int MAXN=8e4+10;
using namespace std;
using namespace std;
int read(){
    int x=0,f=1;char ch=getchar();
    while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
    while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
    return f*x;
}
int n,m,q;int key[MAXN],son[MAXN],num[MAXN],dep[MAXN],fa[MAXN],tp[MAXN],p[MAXN],fp[MAXN];
int rt[MAXN];
int cnt,cnt1,ans;
typedef struct node{
    int l,r,sum;
}node;
node d[205*MAXN];
vector<int>vec[MAXN];
vector<int>qko1,qko2;
vector<int>V1,V2;
vector<int>v1;
void dfs(int v,int pre,int deep){
    num[v]=1;dep[v]=deep+1;fa[v]=pre;
    for(int i=0;i<vec[v].size();i++){
    if(vec[v][i]!=pre){
        dfs(vec[v][i],v,deep+1);
        num[v]+=num[vec[v][i]];
        if(son[v]==-1||num[vec[v][i]]>num[son[v]])son[v]=vec[v][i];
    }
    }
}
void dfs1(int v,int td){
    p[v]=++cnt;fp[p[v]]=v;tp[v]=td;
    if(son[v]!=-1)dfs1(son[v],td);
    for(int i=0;i<vec[v].size();i++){
    if(vec[v][i]!=son[v]&&vec[v][i]!=fa[v])dfs1(vec[v][i],vec[v][i]);
    }
}
void update(int &x,int y,int l,int r,int t,int vul){
    x=++cnt1;d[x]=d[y];d[x].sum+=vul;
    if(l==r)return ;
    int mid=(l+r)>>1;
    if(t<=mid)update(d[x].l,d[y].l,l,mid,t,vul);
    else update(d[x].r,d[x].r,mid+1,r,t,vul);
}
int querty(int l,int r,int t){
     if(l==r)return l;
     int k=0;int mid=(l+r)>>1;
     for(int i=0;i<qko2.size();i++)k+=d[d[qko2[i]].l].sum;
     for(int i=0;i<qko1.size();i++)k-=d[d[qko1[i]].l].sum;
     if(t<=k){
    for(int i=0;i<qko2.size();i++)qko2[i]=d[qko2[i]].l;
    for(int i=0;i<qko1.size();i++)qko1[i]=d[qko1[i]].l;
    return querty(l,mid,t);
     }
     else{
    for(int i=0;i<qko2.size();i++)qko2[i]=d[qko2[i]].r;
    for(int i=0;i<qko1.size();i++)qko1[i]=d[qko1[i]].r;
    return querty(mid+1,r,t-k);
     }
}
int get_id(int x){return x&(-x);}
int slove(int u,int v,int k){
    int uu=tp[u];int vv=tp[v];int num=0;
    V1.clear();V2.clear();qko1.clear();qko2.clear();
    while(uu!=vv){
    if(dep[uu]<dep[vv])swap(uu,vv),swap(u,v);
    V2.push_back(p[u]);
    if(p[uu]!=1)V1.push_back(p[uu]-1);
    num+=dep[u]-dep[uu]+1;u=fa[uu];uu=tp[u];
    }
    if(dep[u]>dep[v])swap(u,v);
    num+=dep[v]-dep[u]+1;
    if(num<k)return -1;
    if(p[u]!=1)V1.push_back(p[u]-1);
    V2.push_back(p[v]);
    for(int i=0;i<V1.size();i++){
    for(int j=V1[i];j>0;j-=get_id(j))qko1.push_back(rt[j]);
    }
    for(int i=0;i<V2.size();i++){
    for(int j=V2[i];j>0;j-=get_id(j))qko2.push_back(rt[j]);
    }
    return querty(1,q,num-k+1);
}
void Update(int v,int vul,int op){
    V1.clear();
    for(int i=p[v];i<=n;i+=get_id(i))V1.push_back(i);
    if(op==0)for(int i=0;i<V1.size();i++)update(rt[V1[i]],rt[V1[i]],1,q,key[v],-1);
    for(int i=0;i<V1.size();i++)update(rt[V1[i]],rt[V1[i]],1,q,vul,1);
    key[v]=vul;
}
typedef struct Node{
    int op,u,v;
}Node;
Node que[MAXN];
int main(){
    n=read();m=read();int u,v,op;q=n+m;
    for(int i=1;i<=n;i++)son[i]=-1;
    for(int i=1;i<=n;i++)key[i]=read(),v1.push_back(key[i]);
    for(int i=1;i<n;i++)u=read(),v=read(),vec[u].push_back(v),vec[v].push_back(u);
    dfs(1,0,0);
    dfs1(1,1);
    for(int i=1;i<=m;i++){
    que[i].op=read(),que[i].u=read(),que[i].v=read();
    if(que[i].op==0)v1.push_back(que[i].v);
    }
    sort(v1.begin(),v1.end());
    int sz=unique(v1.begin(),v1.end())-v1.begin();
    for(int i=1;i<=n;i++)key[i]=lower_bound(v1.begin(),v1.begin()+sz,key[i])-v1.begin()+1;
    for(int i=1;i<=n;i++)Update(i,key[i],1);
    for(int i=1;i<=m;i++){
    //que[i].v=lower_bound(v1.begin(),v1.begin()+sz,que[i].v)-v1.begin()+1;
    if(!que[i].op){que[i].v=lower_bound(v1.begin(),v1.begin()+sz,que[i].v)-v1.begin()+1;;Update(que[i].u,que[i].v,0);}
    else {
        int res=slove(que[i].u,que[i].v,que[i].op);
        if(res==-1)puts("invalid request!");
        else printf("%d\n",v1[res-1]);
    }
    }
    return 0;
}

 
                  1146: [CTSC2008]网络管理Network
                  Time Limit: 50 Sec  Memory Limit: 256 MB
                  Submit: 4275  Solved: 1306
                  [Submit][Status][Discuss]
Description
  M公司是一个非常庞大的跨国公司,在许多国家都设有它的下属分支机构或部门。为了让分布在世界各地的N个
部门之间协同工作,公司搭建了一个连接整个公司的通信网络。该网络的结构由N个路由器和N-1条高速光缆组成。
每个部门都有一个专属的路由器,部门局域网内的所有机器都联向这个路由器,然后再通过这个通信子网与其他部
门进行通信联络。该网络结构保证网络中的任意两个路由器之间都存在一条直接或间接路径以进行通信。 高速光
缆的数据传输速度非常快,以至于利用光缆传输的延迟时间可以忽略。但是由于路由器老化,在这些路由器上进行
数据交换会带来很大的延迟。而两个路由器之间的通信延迟时间则与这两个路由器通信路径上所有路由器中最大的
交换延迟时间有关。作为M公司网络部门的一名实习员工,现在要求你编写一个简单的程序来监视公司的网络状况
。该程序能够随时更新网络状况的变化信息(路由器数据交换延迟时间的变化),并且根据询问给出两个路由器通
信路径上延迟第k大的路由器的延迟时间。【任务】 你的程序从输入文件中读入N个路由器和N-1条光缆的连接信息
,每个路由器初始的数据交换延迟时间Ti,以及Q条询问(或状态改变)的信息。并依次处理这Q条询问信息,它们
可能是: 1. 由于更新了设备,或者设备出现新的故障,使得某个路由器的数据交换延迟时间发生了变化。 2. 查
询某两个路由器a和b之间的路径上延迟第k大的路由器的延迟时间。
Input
第一行为两个整数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大的路由器的延迟时间。
注意N,Q<=80000,任意一个路由器在任何时刻都满足延迟时间小于10^8。
对于所有询问满足0<=K<=N
Output
对于每一个第二种询问(k>0),输出一行。包含一个整数为相应的延迟时间。
如果路径上的路由器不足k个,则输出信息“invalidrequest!”
(全部小写不包含引号,两个单词之间有一个空格)。
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!

posted @ 2018-08-05 16:04  wang9897  阅读(132)  评论(0编辑  收藏  举报