【BZOJ1146】网络管理,整体二分

版权声明:不转不是中国人!(滑稽) https://blog.csdn.net/xym_CSDN/article/details/72854685

传送门
好久没更新题解了,感觉这道题思路不难,但做法挺多的,我大概能想到四种做法,如果有神犇还有其他好方法请在下方评论
1.树链剖分,每条重链维护一颗平衡树
修改直接做 logn
查询时二分答案,查找路径上重链中的平衡树,复杂度 log3n
总复杂度 O(nlogn+qlog3n )
常数大 不好写(因为set不能查询排名)但是是在线做法
2.带修主席树,维护每个叶子到根节点路径上的权值
修改直接做 log2n
查询时把 log 个主席树放在一起查做到 log2n
(感谢lucida的提醒)
总复杂度 O(nlog2n+qlog2n)
常数中等,代码复杂度中等,可以做到在线
3.带修树上莫队,用树状数组维护插入和删除,查询时二分答案
总复杂度 O(q(n23logn+log2n))
基本过不了,离线做法
4.整体二分,然后用树链剖分+树状数组维护权值
总复杂度 O(nlogn+qlog3n)
常数较小,代码复杂度中等,离线做法
(可能有复杂度分析不正确的地方,望指正)
整体二分中的单点修改操作,我用的方法是先减去之前的权值,再加上新的权值,所以修改操作相当于是原先的两倍
“第k大值”可以在求过lca后变为”求第k小值“
代码可读性不是很高。。。见谅
好像整体二分是可以做到 log2n 的?算了不管了。。。
代码:

#include<cstdio>
#include<algorithm>
#include<vector>
using namespace std;
int n,m;
int a[80005],b[110005],ans[30005],dfn[80005],fa[80005],dep[80005],son[80005],siz[80005],top[80005],d[80005];
vector<int>e[80005];
struct opt{
    int k,x,y,id;
}q[140005],l[140005],r[140005];
int in()
{
    int t=0;char ch=getchar();
    for (;ch<'0'||ch>'9';ch=getchar());
    for (;ch>='0'&&ch<='9';ch=getchar()) t=t*10+(ch^48);
    return t;
}
void dfs1(int x)
{
    siz[x]=1;
    for (int v,i=0;i<e[x].size();++i)
    {
        v=e[x][i];
        if (v==fa[x]) continue;
        fa[v]=x;
        dep[v]=dep[x]+1;
        dfs1(v);
        siz[x]+=siz[v];
        son[x]=(siz[son[x]]>siz[v]?son[x]:v);
    }
}
void dfs2(int x,int tp)
{
    top[x]=tp;
    dfn[x]=++dfn[0];
    if (son[x]) dfs2(son[x],tp);
    for (int i=0;i<e[x].size();++i)
        if (e[x][i]!=fa[x]&&e[x][i]!=son[x]) dfs2(e[x][i],e[x][i]);
}
void add(int x,int val)
{
    for (;x<=n;x+=x&-x) d[x]+=val;
}
int get(int x)
{
    int t=0;
    for (;x;x-=x&-x) t+=d[x];
    return t;
}
int cal(int x,int y)
{
    int t=0;
    for (;top[x]!=top[y];x=fa[top[x]])
    {
        if (dep[top[x]]<dep[top[y]]) swap(x,y);
        t+=get(dfn[x])-get(dfn[top[x]]-1);
    }
    if (dep[x]<dep[y]) swap(x,y);
    return t+get(dfn[x])-get(dfn[y]-1);
}
int lca(int x,int y)
{
    for (;top[x]!=top[y];x=fa[top[x]])
        if (dep[top[x]]<dep[top[y]]) swap(x,y);
    return dep[x]<dep[y]?x:y;
}
void solve(int L,int R,int Lo,int Ro)
{
    if (L==R)
    {
        for (int i=Lo;i<=Ro;++i)
            if (q[i].k)
                if (q[i].k>0) ans[q[i].id]=b[R];
                else ans[q[i].id]=-1;
        return;
    }
    int mid=L+R>>1,lc=0,rc=0;
    for (int t,i=Lo;i<=Ro;++i)
        if (q[i].k)
        {
            t=cal(q[i].x,q[i].y);
            if (t>=q[i].k) l[++lc]=q[i];
            else q[i].k-=t,r[++rc]=q[i];
        }
        else
        {
            if (q[i].y<=mid)
                l[++lc]=q[i],
                add(dfn[q[i].x],q[i].id);
            else
                r[++rc]=q[i];
        }
    for (int i=Lo;i<=Ro;++i)
        if (!q[i].k&&q[i].y<=mid) add(dfn[q[i].x],-q[i].id);
    for (int i=Lo;i<=Lo+lc-1;++i) q[i]=l[i-Lo+1];
    for (int i=Lo+lc;i<=Ro;++i) q[i]=r[i-Lo-lc+1];
    solve(L,mid,Lo,Lo+lc-1);
    solve(mid+1,R,Lo+lc,Ro);
}
main()
{
    n=in();m=in();
    for (int i=1;i<=n;++i)
        q[i]=(opt){0,i,a[i]=in(),1},
        b[++b[0]]=q[i].y;
    for (int u,v,i=1;i<n;++i)
        u=in(),v=in(),
        e[u].push_back(v),
        e[v].push_back(u);
    dfs1(1);
    dfs2(1,1);
    int cnt=0,qq=n;
    for (int i=1;i<=m;++i)
    {
        q[++qq]=(opt){in(),in(),in(),0};
        if (q[qq].k)
        {
            q[qq].id=++cnt;
            q[qq].k=dep[q[qq].x]+dep[q[qq].y]-2*dep[lca(q[qq].x,q[qq].y)]+2-q[qq].k;
            if (q[qq].k<=0) q[qq].k=-1;
        }
        else
        {
            b[++b[0]]=q[qq].y;
            q[qq].id=1;
            q[++qq]=q[qq-1];
            q[qq].id=-1;
            q[qq].y=a[q[qq].x];
            a[q[qq].x]=q[qq-1].y;
            swap(q[qq],q[qq-1]);
        }
    }
    sort(b+1,b+b[0]+1);
    b[0]=unique(b+1,b+b[0]+1)-b-1;
    for (int i=1;i<=qq;++i)
        if (!q[i].k) q[i].y=lower_bound(b+1,b+b[0]+1,q[i].y)-b;
    solve(1,b[0],1,qq);
    for (int i=1;i<=cnt;++i)
        if (ans[i]==-1) puts("invalid request!");
        else printf("%d\n",ans[i]);
}

猜你喜欢

转载自blog.csdn.net/xym_CSDN/article/details/72854685