zoukankan      html  css  js  c++  java
  • 牛客多校第九场 E Eyjafjalla (倍增+主席树

    题意,有一个树,根节点为1,每个节点都有一个温度,保证离根节点越近温度越高。

    现在有q次询问,每次在城市k爆发一种生存温度在[l,r]的病毒,问病毒会蔓延几个城市。

    思路:赛场上其实是出了的,但是这道题出了点锅,而且感觉是一道还可以的数据结构题,所以记录一下。

    首先对于一棵树,我们肯定不好直接从任意一个点找齐所有的点,但是如果是从根节点往下找,那就会好找很多,因为针对某棵子树我们维护各种都系都会方便很多。

    那么对于每一次询问,我们不妨先找到离根节点最近的刚好小于等于r的城市。这一步可以用倍增找,当然树链剖分之类的算法应该也行,但是倍增写起来非常方便。

    当我们找到了这个r,那么问题就转换成了对于一棵子树,我们找他下面点权大于等于l的点数,这个东西我们可以对dfs序建主席树来维护。

    赛场上的锅出在,为了方便搞出一段区间,我直接把dfs序翻倍搞成了括号化序列,但是忘记把数组空间也翻倍了,导致wa了好久,然后他不报RE又没往那想,debug了好久才出

    下附代码:

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn=1e5+5;
    const int max0=20;
    int stampk;
    int fa[maxn][max0+1];
    int Next[maxn*2],to[maxn*2],head[maxn],tot=0;
    int dep[maxn];
    int dfnl[maxn],dfnr[maxn];
    int t[maxn];
    int sum[(maxn*2)<<5];
    int ls[(maxn*2)<<5],rs[(maxn*2)<<5];
    int cnt[maxn*2],b[maxn*2];
    int rt[(maxn*2)<<5];
    int tt=0;
    void build(int l,int r,int root)
    {
        sum[root]=0;
        if(l==r)
            return ;
        int mid=l+r>>1;
        build(l,mid,ls[root]=++tt);
        build(mid+1,r,rs[root]=++tt);
    }
    void update(int l,int r,int root,int last,int pos)
    {
        ls[root]=ls[last];
        rs[root]=rs[last];
        sum[root]=sum[last]+1;
        if(l==r)
            return ;
        int mid=l+r>>1;
        if(mid>=pos)
            update(l,mid,ls[root]=++tt,ls[last],pos);
        else
            update(mid+1,r,rs[root]=++tt,rs[last],pos);
    }
    int query(int l,int r,int root,int last,int pos)
    {
        if(l==r)
            return sum[root]-sum[last];
        int mid=l+r>>1;
        int ans;
        if(pos<=mid)
            ans=query(l,mid,ls[root],ls[last],pos)+sum[rs[root]]-sum[rs[last]];
        else
            ans=query(mid+1,r,rs[root],rs[last],pos);
        return ans;
    }
    void add(int a,int b){
        Next[tot]=head[a],to[tot]=b;
        head[a]=tot++;
    }
    void dfs1(int x)
    {
        for(int i=1;i<=max0;i++)
            if(fa[x][i-1])   //在dfs(x)之前,x的父辈们的fa数组都已经计算完毕,所以可以用来计算x
                fa[x][i]=fa[fa[x][i-1]][i-1];
            else break;    //如果x已经没有第2^(i-1)个父亲了,那么也不会有更远的父亲,直接break
        for(int i=head[x]; i!=-1; i=Next[i]){
            int y=to[i];
            if(y!=fa[x][0])     //如果i不是x的父亲就是x的儿子
            {
                fa[y][0]=x;       //记录儿子的第一个父亲是x
                dep[y]=dep[y]+1;      //处理深度
                dfs1(y);
            }
        }
    }
    void dfs(int x,int pre){
        dfnl[x]=++stampk;
        cnt[stampk]=x;
        for (int i=head[x]; i!=-1; i=Next[i]){
            int y=to[i];
            if (y!=pre)
                dfs(y,x);
        }
        dfnr[x]=++stampk;
    }
    int find(int x,int up){
        int ad=max0;
        while (fa[x][ad]==0 && ad>=0) ad--;
        while (ad>=0){
            while (fa[x][ad]==0 && ad>=0) ad--;
            while (t[fa[x][ad]]>up && ad>=0) ad--;
            if (ad<0) break;
            x=fa[x][ad];
        }
        return x;
    }
    int main(){
        int n;
        scanf("%d",&n);
        memset(fa,0,sizeof(fa));
        tt=0;
        build(1,2*n,rt[0]=++tt);
        for (int i=1; i<=n; i++){
            head[i]=-1;
        }
        for (int i=1; i<n; i++){
            int x,y;
            scanf("%d%d",&x,&y);
            add(x,y);
            add(y,x);
        }
        dfs1(1);
        stampk=0;
        dfs(1,-1);
        for (int i=1; i<=n; i++) {
            scanf("%d",&t[i]);
            b[i]=t[i];
        }
        b[n+1]=0;
        sort(b+1,b+2+n);
        int all=unique(b+1,b+2+n)-b-1;
        for (int i=1; i<=2*n; i++){
            int tmp=lower_bound(b+1,b+1+all,t[cnt[i]])-b;
            if (tmp==1) tmp=0;
            update(1,2*n,rt[i]=++tt,rt[i-1],tmp);
        }
        int q;
        scanf("%d",&q);
        while (q--){
            int p,l,r;
            scanf("%d%d%d",&p,&l,&r);
            if (t[p]<l || t[p]>r){
                printf("0
    ");
                continue;
            }
            int zz=find(p,r);
         //   printf("%d
    ",zz);
        //    printf("%d %d %d
    ",dfnr[zz],dfnl[zz]-1,lower_bound(b,b+1+all,l)-b+1);
            printf("%d
    ",query(1,2*n,rt[dfnr[zz]],rt[dfnl[zz]-1],lower_bound(b+1,b+1+all,l)-b));
        }
    }
    View Code
  • 相关阅读:
    Python-面向对象(一)-Day7
    Python-模块使用-Day6
    Python-迭代器&生成器&装饰器&软件目录结构规范-Day5
    Python-函数-Day4
    Python-字典、集合、字符编码、文件操作整理-Day3
    Python-字符串及列表操作-Day2
    Python-基础学习-Day1
    解决安装Weblogic domain卡住问题(Primeton BPS)
    怎样在旅途中拍出好看的照片
    Weblogic启动成功,控制台打不开
  • 原文地址:https://www.cnblogs.com/i-caigou-TT/p/15143505.html
Copyright © 2011-2022 走看看