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

[CTSC2008]网络管理

时间:2018-10-21 23:21:05      阅读:207      评论:0      收藏:0      [点我收藏+]

标签:查询   class   update   uniq   algorithm   inline   在线   names   i++   

[CTSC2008]网络管理

这个题看到维护链上路径,看起来很像是树剖,但是用线段树+树链剖分显然还要二分答案,这就三个log了,于是考虑复杂度更加优秀的做法.
线段树套树状数组(带修改主席树),主席树有道经典的板子题.Dynamic Rankings
那个是区间,这个是树上路径,其实大同小异.根据树的dfn序列,建线段树.
你做修改的时候,相当于把dfn序列中\([dfn[x],dfn[x]+sz[x]-1]\)之间的点修改了嘛.
想象一下一排一模一样整齐的二叉树,优美地排列在你面前,这个时候一下把这些线段树们都压在一坨,每个二叉树的节点都开一个树状数组来维护前缀和.,然后你在这颗棵压扁的线段树上,没走到一个节点,就把这个节点的那个树状数组拿出来,查询或者修改你要的信息.
这样空间复杂度看起来是\(n^2\)的,所以显然要动态开点,树状数组也要动态开点.
注意树上单点修改是区间修改,所以树状数组是差分了的,单点查询相当于前缀和查询.
还有就是一定要离散化你的权值.

又臭又长的代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define maxn 80005
#define mid ((l+r)>>1)
using namespace std;
int n,m,tim,p,tot,Q,cnt1,cnt0,sz;
int seq[maxn],b[maxn<<1],s[maxn*400],lc[maxn*400],rc[maxn*400];
int tmp[2][maxn],dep[maxn],dfn[maxn],fa[maxn][20],size[maxn],rt[maxn];
struct node{int k,a,b;}q[maxn];
int head[maxn],nxt[maxn<<1],to[maxn<<1],cnt;
void add(int u,int v){nxt[++cnt]=head[u];head[u]=cnt;to[cnt]=v;}
inline int lowbit(int x){return x&-x;}
void update(int &x,int l,int r,int pos,int v)
{
    if(!x)x=++p;s[x]+=v;if(l==r)return;
    if(pos<=mid)update(lc[x],l,mid,pos,v);
    else update(rc[x],mid+1,r,pos,v);
}
int query(int l,int r,int k)//树状数组的log个点暴力在线段树上跳
{
    if(l==r)return l;int sum=0;
    for(int i=1;i<=cnt0;i++)sum+=s[lc[tmp[0][i]]];
    for(int i=1;i<=cnt1;i++)sum-=s[lc[tmp[1][i]]];
    if(k<=sum)
    {
        for(int i=1;i<=cnt0;i++)tmp[0][i]=lc[tmp[0][i]];
        for(int i=1;i<=cnt1;i++)tmp[1][i]=lc[tmp[1][i]];
        return query(l,mid,k);
    }
    else
    {
        for(int i=1;i<=cnt0;i++)tmp[0][i]=rc[tmp[0][i]];
        for(int i=1;i<=cnt1;i++)tmp[1][i]=rc[tmp[1][i]];
        return query(mid+1,r,k-sum);
    }
}
void dfs(int u,int ff)
{
    fa[u][0]=ff;dep[u]=dep[ff]+1;dfn[u]=++tim;size[u]=1;
    for(int i=1;i<=17;i++)fa[u][i]=fa[fa[u][i-1]][i-1];
    for(int i=head[u];i;i=nxt[i])
    {
        int v=to[i];if(v==ff)continue;
        dfs(v,u);size[u]+=size[v];
    }
}
int getlca(int x,int y)
{
    if(dep[x]<dep[y])swap(x,y);
    int tt=dep[x]-dep[y];
    for(int i=0;i<=17;i++)
        if(tt&(1<<i))x=fa[x][i];
    if(x==y)return x;
    for(int i=17;i>=0;i--)
        if(fa[x][i]!=fa[y][i])x=fa[x][i],y=fa[y][i];
    return fa[x][0];
}
void init()
{
    cin>>n>>Q;
    for(int i=1;i<=n;i++)scanf("%d",&seq[i]),b[++tot]=seq[i];
    for(int i=1,u,v;i<n;i++)scanf("%d%d",&u,&v),add(u,v),add(v,u);
    for(int i=1;i<=Q;i++)
    {
        scanf("%d%d%d",&q[i].k,&q[i].a,&q[i].b);
        if(!q[i].k)b[++tot]=q[i].b;
    }
    sort(b+1,b+1+tot);sz=unique(b+1,b+1+tot)-b-1;
    for(int i=1;i<=n;i++)seq[i]=lower_bound(b+1,b+1+sz,seq[i])-b;
    dfs(1,0);
    for(int i=1;i<=n;i++)
    {
        for(int j=dfn[i];j<=n;j+=lowbit(j))
            update(rt[j],1,sz,seq[i],1);
        for(int j=dfn[i]+size[i];j<=n;j+=lowbit(j))
            update(rt[j],1,sz,seq[i],-1);
    }
}
int main()
{
    init();
    for(int i=1,x,y;i<=Q;i++)
    {
        x=q[i].a;y=q[i].b;
        if(q[i].k)
        {
            int lca=getlca(x,y),fl=fa[lca][0],len;cnt0=cnt1=0;
            len=dep[x]+dep[y]-dep[lca]-dep[fl];
            for(int j=dfn[x];j>=1;j-=lowbit(j))tmp[0][++cnt0]=rt[j];
            for(int j=dfn[y];j>=1;j-=lowbit(j))tmp[0][++cnt0]=rt[j];
            for(int j=dfn[lca];j>=1;j-=lowbit(j))tmp[1][++cnt1]=rt[j];
            for(int j=dfn[fl];j>=1;j-=lowbit(j))tmp[1][++cnt1]=rt[j];
            if(q[i].k>len)puts("invalid request!");
            else printf("%d\n",b[query(1,sz,len-q[i].k+1)]);
            
        }
        else
        {
            for(int j=dfn[x];j<=n;j+=lowbit(j))
                update(rt[j],1,sz,seq[x],-1);
            for(int j=dfn[x]+size[x];j<=n;j+=lowbit(j))
                update(rt[j],1,sz,seq[x],1);
            seq[x]=lower_bound(b+1,b+1+sz,y)-b;
            for(int j=dfn[x];j<=n;j+=lowbit(j))
                update(rt[j],1,sz,seq[x],1);
            for(int j=dfn[x]+size[x];j<=n;j+=lowbit(j))
                update(rt[j],1,sz,seq[x],-1);
        }
    }
    return 0;
}

[CTSC2008]网络管理

标签:查询   class   update   uniq   algorithm   inline   在线   names   i++   

原文地址:https://www.cnblogs.com/terribleterrible/p/9827550.html

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