• CF893F Subtree Minimum Query 解题报告


    CF893F Subtree Minimum Query

    输入输出格式

    输入格式:

    The first line contains two integers (n) and (r) ( (1<=r<=n<=100000) ) — the number of vertices in the tree and the index of the root, respectively.

    The second line contains n integers (a_{1},a_{2},...,a_{n}) ( (1<=a_{i}<=10^{9}) ) — the numbers written on the vertices.

    Then (n-1) lines follow, each containing two integers (x) and (y) ( (1<=x,y<=n) ) and representing an edge between vertices (x) and (y) . It is guaranteed that these edges form a tree.

    Next line contains one integer (m) ( (1<=m<=10^{6}) ) — the number of queries to process.

    Then m lines follow, (i) -th line containing two numbers (p_{i}) and (q_{i}) , which can be used to restore (i) -th query ( (1<=p_{i},q_{i}<=n) ).

    (i) -th query can be restored as follows:

    Let last last be the answer for previous query (or (0) if (i=1) ). Then (x_{i}=((p_{i}+last) mod n)+1), and (k_{i}=(q_{i}+last) mod n) .

    输出格式:

    Print (m) integers. (i) -th of them has to be equal to the answer to (i) -th query.


    题意大概就是给你一个有跟有点权的树,边权均为(1),每次询问一个点子树中距离Ta不超过(k)距离的点的最小点权。

    发现(dfs)序限定子树是一个区间,可以放在线段树上,然后深度确定另一个区间,套一颗平衡树,就可以了。

    事实上这道题还有一个高妙的做法,我并不会。

    说不定以后会看一看呐


    Code:

    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #define ls ch[now][0]
    #define rs ch[now][1]
    const int N=1e5+10;
    int ch[N*30][2],dep[N*30],dat[N*30],mx[N*30],val[N*30],root[N<<2],tot;
    int min(int x,int y){return x<y?x:y;}
    void updata(int now){mx[now]=min(dat[now],min(mx[ls],mx[rs]));}
    void split(int now,int k,int &x,int &y)
    {
        if(!now){x=y=0;return;}
        if(dep[now]<=k)
            x=now,split(rs,k,rs,y);
        else
            y=now,split(ls,k,x,ls);
        updata(now);
    }
    int Merge(int x,int y)
    {
        if(!x||!y) return x+y;
        if(val[x]<val[y])
        {
            ch[x][1]=Merge(ch[x][1],y);
            updata(x);
            return x;
        }
        else
        {
            ch[y][0]=Merge(x,ch[y][0]);
            updata(y);
            return y;
        }
    }
    int New(int d,int de)
    {
        val[++tot]=rand(),dat[tot]=mx[tot]=d,dep[tot]=de;
        return tot;
    }
    void Insert(int id,int d,int de)
    {
        int x,y;
        split(root[id],de,x,y);
        root[id]=Merge(x,Merge(New(d,de),y));
    }
    int ask(int id,int de)
    {
        int x,y,z;
        split(root[id],de,x,y);
        z=mx[x];
        root[id]=Merge(x,y);
        return z;
    }
    int query(int id,int L,int R,int l,int r,int de)
    {
        if(l==L&&r==R)
            return ask(id,de);
        int Mid=L+R>>1;
        if(r<=Mid) return query(id<<1,L,Mid,l,r,de);
        else if(l>Mid) return query(id<<1|1,Mid+1,R,l,r,de);
        else return min(query(id<<1,L,Mid,l,Mid,de),query(id<<1|1,Mid+1,R,Mid+1,r,de));
    }
    int Next[N<<1],to[N<<1],head[N],cnt;
    void add(int u,int v)
    {
        to[++cnt]=v,Next[cnt]=head[u],head[u]=cnt;
    }
    int dfn[N],low[N],Dep[N],ha[N],dfs_clock,n,m,rt,a[N];
    void dfs(int now,int fa)
    {
        dfn[now]=++dfs_clock;
        ha[dfs_clock]=now;
        for(int i=head[now];i;i=Next[i])
        {
            int v=to[i];
            if(v!=fa)
                Dep[v]=Dep[now]+1,dfs(v,now);
        }
        low[now]=dfs_clock;
    }
    void build(int id,int l,int r)
    {
        for(int i=l;i<=r;i++)
            Insert(id,a[ha[i]],Dep[ha[i]]);
        if(l==r) return;
        int mid=l+r>>1;
        build(id<<1,l,mid),build(id<<1|1,mid+1,r);
    }
    int main()
    {
        memset(dat,0x3f,sizeof(dat));
        memset(mx,0x3f,sizeof(mx));
        scanf("%d%d",&n,&rt);
        for(int i=1;i<=n;i++) scanf("%d",a+i);
        for(int u,v,i=1;i<n;i++)
        {
            scanf("%d%d",&u,&v);
            add(u,v),add(v,u);
        }
        dfs(rt,0);
        build(1,1,n);
        scanf("%d",&m);
        int las=0;
        for(int p,q,i=1;i<=m;i++)
        {
            scanf("%d%d",&p,&q);
            p=(p+las)%n+1,q=(q+las)%n;
            printf("%d
    ",las=query(1,1,n,dfn[p],low[p],Dep[p]+q));
        }
        return 0;
    }
    
    

    2018.10.13

  • 相关阅读:
    http编程中的get和post混合使用方式
    SQLServer实现作业依赖(非步骤)
    SQLServer实现两个库的字段长度自动更新
    Python+SQLite数据库实现服务端高并发写入
    sqlite数据库相关使用
    sqlite语法
    VBA关键字总结
    VS2005 .net2.0 TreeView.设置SelectedNodeStyle控制TreeView中选定节点的外观的
    SQLSERVER 2005 如何给sa用户设置空密码?
    解决超过远程连接数而无法连接服务器的问题 踢出已断开用户
  • 原文地址:https://www.cnblogs.com/butterflydew/p/9781579.html
Copyright © 2020-2023  润新知