zoukankan      html  css  js  c++  java
  • BZOJ3635谈笑风生

    一些闲话

    这题方法好多啊QAQ,离线有BIT、长链剖分,在线有线段树合并,主席树等。
    要我出题绝对不可能放离线过。。。

    题面链接

    权限题诶
    洛谷

    题意简述

    简单的看一下题意,就是给定(a),求任何一个距(a)距离不超过给定的(k)(b),然后求一个(c)使得是(a,b)的后代。

    sol

    我相信你已经看出来了,(abc)在一条直上直下的链上,不过这并没有什么用。我们考虑当(b)(a)的祖先时,(a)子树内所有除它自己以外的点都可以做(c)这个可以直接统计。当(a)(b)的祖先时,(b)子树内所有除它以外的点都可以做(c)。那么每个节点搞一个权值线段树维护一下就可以辣。然后显然这个空间复杂度会爆炸,于是就可以愉快的线段树合并辣。

    #include<vector>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define gt getchar()
    #define ll long long
    #define File(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout)
    inline int in()
    {
        int k=0;char ch=gt;
        while(ch<'-')ch=gt;
        while(ch>'-')k=k*10+ch-'0',ch=gt;
        return k;
    }
    const int N=600005;
    std::vector<int>Q[N],id[N];
    using std::min;
    using std::max;
    struct node
    {
        ll siz;int lc,rc;
    }t[N*30];
    int tot,opt;
    ll query(int L,int R,int l,int r,int x)
    {
        if(!x)return 0;
        if(L<=l&&r<=R)return t[x].siz;
        int mid=l+r>>1;ll res=0;
        if(mid>=L)res+=query(L,R,l, mid ,t[x].lc);
        if(mid< R)res+=query(L,R,mid+1,r,t[x].rc);
        return res;
    }
    void upd(int l,int r,int pos,int &x,int v)
    {
        if(!x)x=++tot;t[x].siz+=v;
        if(l==r)return;
        int mid=l+r>>1;
        if(mid>=pos)upd(l,mid,pos,t[x].lc,v);
        else upd(mid+1,r,pos,t[x].rc,v);
    }
    int merge(int u,int v,int l,int r)
    {
        if(!u||!v)return u|v;
        int mid=l+r>>1,x=++tot;
        t[x].siz=t[u].siz+t[v].siz;
        t[x].lc=merge(t[u].lc,t[v].lc,l, mid );
        t[x].rc=merge(t[u].rc,t[v].rc,mid+1,r);
        return x;
    }
    int siz[N],rt[N],a[N],b[N],fa[N],head[N],to[N],nxt[N],cnt,sz,dep[N];
    ll ans[N];
    inline void add(int u,int v)
    {
        to[++cnt]=v,nxt[cnt]=head[u],head[u]=cnt;
        to[++cnt]=u,nxt[cnt]=head[v],head[v]=cnt;
    }
    void dfs(int u,int pa=0)
    {
        dep[u]=dep[pa]+1;siz[u]=1;//printf("u=%d pa=%d
    ",u,pa);
        for(int i=head[u];i;i=nxt[i])
            if(to[i]!=pa)
                dfs(to[i],u),siz[u]+=siz[to[i]];
        upd(1,sz,dep[u],rt[u],siz[u]-1);
        if(pa)rt[pa]=merge(rt[pa],rt[u],1,sz);
    }
    int main()
    {
        int n=in(),q=in();sz=n;
        for(int i=1;i<n;++i)add(in(),in());
        dfs(1);
        for(int i=1;i<=q;++i)
        {
            int x=in(),y=in();
            printf("%lld
    ",query(dep[x]+1,dep[x]+y,1,n,rt[x])+1ll*(siz[x]-1)*min(dep[x]-1,y));
        }
        return 0;
    }
    
  • 相关阅读:
    java bigdecimal (java double也时会失真)
    图像二维频谱的理解
    设计模式:装饰器模式实现 固定类功能
    c# winform 技术提升
    c# 多态的美丽(虚方法、抽象、接口实现)
    5天玩转C#并行和多线程编程
    [C#防止反编译].NET 产品版权保护方案 (.NET源码加密保护)
    用Ngen指令加快C#程序的启动速度
    cmd 批处理制作
    c#程序打包、机器代码生成(Ngen.exe)
  • 原文地址:https://www.cnblogs.com/cx233666/p/9721869.html
Copyright © 2011-2022 走看看