码迷,mamicode.com
首页 > 其他好文 > 详细

P4175 [CTSC2008]网络管理

时间:2019-04-03 19:25:40      阅读:168      评论:0      收藏:0      [点我收藏+]

标签:inf   tin   dep   long   list   nod   name   lca   type   

题目链接

题意分析

带修改树链第\(k\)

首先我们使用树链剖分将树上问题转化为区间问题

然后对于当前修改 我们直接修改即可

对于链上第\(k\)大 我们先求一个总点数

转化为链上第\(k\)

然后我们将\(x\)\(y\)之间所有的重链都提出来

那么在\(dfs\)序上就是一堆连续区间

而且最多\(log\)

类比于区间问题维护一个区间

我们顶多维护\(log\)个区间

然后同时跳即可 详细见代码即可

CODE:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<cstdlib>
#include<string>
#include<queue>
#include<map>
#include<stack>
#include<list>
#include<set>
#include<deque>
#include<vector>
#include<ctime>
#define ll long long
#define inf 0x7fffffff
#define N 80008
#define IL inline
#define M 1008611
#define D double
#define ull unsigned long long
#define R register
using namespace std;
template<typename T>IL void read(T &_)
{
    T __=0,___=1;char ____=getchar();
    while(!isdigit(____)) {if(____=='-') ___=0;____=getchar();}
    while(isdigit(____)) {__=(__<<1)+(__<<3)+____-'0';____=getchar();}
    _=___ ? __:-__;
}
/*-------------OI使我快乐-------------*/
int n,m,tot,cnt,all;
struct Node
{
    int fro,tox,cnta,cntb;
    int cdy[30],wzy[30];
}e[N];
struct Qury
{
    int k,a,b;
}ex[N];
int num[N],res[N<<1];
int to[N<<1],nex[N<<1],head[N];
int dep[N],fa[N],ssiz[N],son[N];
int top[N],dfn[N],wt[N];
int root[N],lson[M*40],rson[M*40],siz[M*40];
IL void add(int x,int y)
{to[++tot]=y;nex[tot]=head[x];head[x]=tot;}
IL int get_hash(int x){return lower_bound(res+1,res+cnt+1,x)-res;}
IL void insert(int &now,int le,int ri,int pos,int d)
{
    if(!now) now=++tot;siz[now]+=d;
    if(le==ri) return;
    int mid=(le+ri)>>1;
    if(pos<=mid) insert(lson[now],le,mid,pos,d);
    else insert(rson[now],mid+1,ri,pos,d);
}
IL void Add(int x,int pos,int d)
{
    for(R int i=x;i<=n;i+=i&-i)
    insert(root[i],1,cnt,pos,d);
}
IL void get_ready()
{
    for(R int i=1;i<=all;++i)
    {
        e[i].cnta=0;e[i].cntb=0;
        for(R int j=e[i].fro-1;j>0;j-=j&-j) e[i].cdy[++e[i].cnta]=root[j];
        for(R int j=e[i].tox;j>0;j-=j&-j) e[i].wzy[++e[i].cntb]=root[j];
    }
}
IL void dfs1(int now,int fat)
{
    dep[now]=dep[fat]+1;fa[now]=fat;ssiz[now]=1;
    int maxsiz=-1;
    for(R int i=head[now];i;i=nex[i])
    {
        int v=to[i];
        if(v==fat) continue;
        dfs1(v,now);
        ssiz[now]+=ssiz[v];
        if(ssiz[v]>maxsiz) maxsiz=siz[v],son[now]=v;
    }
}
IL void dfs2(int now,int topf)
{
    top[now]=topf;dfn[now]=++all;wt[all]=now;
    if(!son[now]) return;dfs2(son[now],topf);
    for(R int i=head[now];i;i=nex[i])
    {
        int v=to[i];
        if(v==fa[now]||v==son[now]) continue;
        dfs2(v,v);
    }
}
IL int LCA(int nowx,int nowy)
{
    while(top[nowx]!=top[nowy])
    {
        if(dep[top[nowx]]<dep[top[nowy]]) swap(nowx,nowy);
        nowx=fa[top[nowx]];
    }
    if(dep[nowx]>dep[nowy]) swap(nowx,nowy);
    return nowx;
}
IL void QuryRange(int nowx,int nowy)
{//我们提出所有的dfs序的连续区间
    while(top[nowx]!=top[nowy])
    {
        if(dep[top[nowx]]<dep[top[nowy]]) swap(nowx,nowy);
        ++all;e[all].fro=dfn[top[nowx]];e[all].tox=dfn[nowx];
        nowx=fa[top[nowx]];
    }
    if(dep[nowx]>dep[nowy]) swap(nowx,nowy);
    ++all;e[all].fro=dfn[nowx];e[all].tox=dfn[nowy];
    return;
}
IL int getsiz(int x,int y)
{
    int lca=LCA(x,y);
    return dep[x]+dep[y]-dep[lca]-dep[fa[lca]];
}
IL int getsum()
{//类似于动态主席树
    int res=0;
    for(R int i=1;i<=all;++i)
    {
        for(R int j=1;j<=e[i].cnta;++j) res-=siz[lson[e[i].cdy[j]]];
        for(R int j=1;j<=e[i].cntb;++j) res+=siz[lson[e[i].wzy[j]]];
    }
    return res;
}
IL void pushcdy()
{
    for(R int i=1;i<=all;++i)
    {
        for(R int j=1;j<=e[i].cnta;++j) e[i].cdy[j]=lson[e[i].cdy[j]];
        for(R int j=1;j<=e[i].cntb;++j) e[i].wzy[j]=lson[e[i].wzy[j]];
    }
}
IL void pushwzy()
{
    for(R int i=1;i<=all;++i)
    {
        for(R int j=1;j<=e[i].cnta;++j) e[i].cdy[j]=rson[e[i].cdy[j]];
        for(R int j=1;j<=e[i].cntb;++j) e[i].wzy[j]=rson[e[i].wzy[j]];
    }
}
IL int getrnk(int le,int ri,int k)
{
    while(le<ri)
    {
        int mid=(le+ri)>>1;
        int tmp=getsum();
        if(k<=tmp) ri=mid,pushcdy();
        else k-=tmp,le=mid+1,pushwzy();
    }
    return le;
}
int main()
{
//  freopen("222.in","r",stdin);
//  freopen("222.out","w",stdout);
    read(n);read(m);
    for(R int i=1;i<=n;++i) read(num[i]),res[++cnt]=num[i];
    for(R int i=1,x,y;i<n;++i)
    {
        read(x);read(y);
        add(x,y);add(y,x);
    }
    for(R int i=1;i<=m;++i)
    {
        read(ex[i].k);read(ex[i].a);read(ex[i].b);
        if(ex[i].k==0) res[++cnt]=ex[i].b;
    } 
    
    sort(res+1,res+cnt+1);cnt=unique(res+1,res+cnt+1)-res-1;
    for(R int i=1;i<=n;++i) num[i]=get_hash(num[i]);
    dfs1(1,0);dfs2(1,1);
    tot=0;for(R int i=1;i<=n;++i) Add(i,num[wt[i]],1);
    for(R int i=1;i<=m;++i)
    {
        all=0;
        if(ex[i].k==0)
        {
            Add(dfn[ex[i].a],num[ex[i].a],-1);
            num[ex[i].a]=get_hash(ex[i].b);
            Add(dfn[ex[i].a],num[ex[i].a],1);
        }
        else
        {
            QuryRange(ex[i].a,ex[i].b);get_ready();
            int all=getsiz(ex[i].a,ex[i].b);
            if(all<ex[i].k) puts("invalid request!");
            else printf("%d\n",res[getrnk(1,cnt,all-ex[i].k+1)]);
        }
    }
    return 0;
}

HEOI 2019 RP++

P4175 [CTSC2008]网络管理

标签:inf   tin   dep   long   list   nod   name   lca   type   

原文地址:https://www.cnblogs.com/LovToLZX/p/10650882.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!