zoukankan      html  css  js  c++  java
  • NOIP 模拟 $14; ext{影魔}$

    题解 (by;;zjvarphi)

    不是原题

    一道(对我来说)很需要技巧的题

    对于颜色数如何处理

    1. 离线,将子树转化为 (dfs) 序,但这种做法无法处理深度

    2. 我们按照深度加点(可以通过 (bfs) 实现),对于加到的每一个点,寻找和它颜色相同的点的 (dfs) 序,记录前趋和后继( (set) ),
      将这个点和前趋,和后继的 (lca) 权值减 (1),将前趋和后继的 (lca) 权值加 (1)

    至于如何处理深度,可以维护一棵可持久化线段树,对于每一层在 (dfs) 序上建立,查询时直接区间查询相应深度的那棵线段树。

    Code
    #include<bits/stdc++.h>
    #define ri register signed
    #define p(i) ++i
    using namespace std;
    namespace IO{
        char buf[1<<21],*p1=buf,*p2=buf;
        #define gc() p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++
        template<typename T>inline void read(T &x) {
            ri f=1;x=0;register char ch=gc();
            while(ch<'0'||ch>'9') {if (ch=='-') f=0;ch=gc();}
            while(ch>='0'&&ch<='9') {x=(x<<1)+(x<<3)+(ch^48);ch=gc();}
            x=f?x:-x;
        }
    }
    using IO::read;
    namespace nanfeng{
        #define pb(x) push_back(x)
        #define cmax(x,y) ((x)>(y)?(x):(y))
        #define cmin(x,y) ((x)>(y)?(y):(x))
        #define FI FILE *IN
        #define FO FILE *OUT
        static const int N=1e5+7;
        set<int> ste[N];
        set<int>::iterator it,ti;
        int first[N],col[N],l[N],r[N],bc[N],que[N],head[N],st[N<<1][19],dep[N],mxdep[N],lg[N<<1],ol,dfn,t=1,n,m;
        struct edge{int v,nxt;}e[N];
        inline void add(int u,int v) {e[t].v=v,e[t].nxt=first[u],first[u]=t++;}
        struct Seg{
            #define ls(x) T[x].l
            #define rs(x) T[x].r
            #define up(x) T[x].w=T[ls(x)].w+T[rs(x)].w
            struct segmenttree{int l,r,w;}T[N<<6];
            int rt[N],tot;
            inline int New(int pre) {T[p(tot)]=T[pre];return tot;}
            void update(int &x,int p,int k,int l,int r) {
                if (!x) x=p(tot);
                if (l==r) {T[x].w+=k;return;}
                int mid(l+r>>1);
                if (p<=mid) update(ls(x),p,k,l,mid); 
                else update(rs(x),p,k,mid+1,r);
                up(x);
            }
            int merge(int x,int y) {
                if (!x||!y) return (x|y);
                T[x].w+=T[y].w;
                ls(x)=merge(ls(x),ls(y));
                rs(x)=merge(rs(x),rs(y));
                return x;
            }
            int query(int x,int l,int r,int lt,int rt) {
                if (!x) return 0;
                if (l<=lt&&rt<=r) return T[x].w;
                int mid(lt+rt>>1),res(0);
                if (l<=mid) res+=query(ls(x),l,r,lt,mid);
                if (r>mid) res+=query(rs(x),l,r,mid+1,rt);
                return res;
            }
        }T;
        void dfs(int x) {
            bc[l[x]=p(dfn)]=x;
            head[st[p(ol)][0]=x]=ol;
            mxdep[x]=dep[x];
            for (ri i(first[x]),v;i;i=e[i].nxt) 
                dep[v=e[i].v]=dep[st[p(ol)][0]=x]+1,dfs(v),mxdep[x]=cmax(mxdep[x],mxdep[v]);
            r[x]=dfn;
        }
        inline void init_rmq() {
            dep[1]=1;dfs(1);
            for (ri i(2);i<=ol;p(i)) lg[i]=lg[i>>1]+1;
            int k=lg[ol];
            for (ri j(1);j<=k;p(j)) {
                ri len=(1<<j);
                for (ri i(1);i+len-1<=ol;p(i)) {
                    int x1=st[i][j-1],x2=st[i+(1<<j-1)][j-1];
                    st[i][j]=dep[x1]<dep[x2]?x1:x2;
                }
            }
        }
        inline int Getlca(int u,int v) {
            if (head[u]>head[v]) swap(u,v);
            int k=lg[head[v]-head[u]+1];
            int x1=st[head[u]][k],x2=st[head[v]-(1<<k)+1][k];
            return dep[x1]<dep[x2]?x1:x2;
        }
        inline void bfs() {
            ri hd=1,tl=0,mxd;
            que[p(tl)]=1;
            while(hd<=tl) {
                ri x=que[hd++],cl=col[x],pre=0,nxt=0;
                T.update(T.rt[dep[x]],l[x],1,1,n);
                ste[cl].insert(l[x]);
                it=ti=ste[cl].find(l[x]);
                if (ti!=ste[cl].begin()) {
                    pre=bc[*--ti];
                    T.update(T.rt[dep[x]],l[Getlca(pre,x)],-1,1,n);
                } 
                if (it!=--ste[cl].end()) {
                    nxt=bc[*p(it)];
                    T.update(T.rt[dep[x]],l[Getlca(x,nxt)],-1,1,n);
                }
                if (pre&&nxt) T.update(T.rt[dep[x]],l[Getlca(pre,nxt)],1,1,n);
                for (ri i(first[x]);i;i=e[i].nxt) que[p(tl)]=e[i].v; 
            }
            mxd=dep[que[tl]];
            for (ri i(2);i<=mxd;p(i)) T.merge(T.rt[i],T.rt[i-1]);
        }
        inline int main() {
            // FI=freopen("nanfeng.in","r",stdin);
            // FO=freopen("nanfeng.out","w",stdout);
            read(n),read(m);
            for (ri i(1);i<=n;p(i)) read(col[i]);
            for (ri i(2),u;i<=n;p(i)) read(u),add(u,i);
            init_rmq();
            bfs();
            for (ri i(1),x,d;i<=m;p(i)) {
                read(x),read(d);
                if (dep[x]+d>mxdep[x]) 
                    printf("%d
    ",T.query(T.rt[mxdep[x]],l[x],r[x],1,n));
                else printf("%d
    ",T.query(T.rt[dep[x]+d],l[x],r[x],1,n));
            }
            return 0;
        } 
    }
    int main() {return nanfeng::main();}
    
  • 相关阅读:
    CSS团队协作规范
    百度前端学院-基础学院-第四课
    百度前端学院-基础学院-第三课
    百度前端学院-基础学院-第二课
    vue(三)-父子组件通信
    setTimeout()与clearTimeout()
    vue(二)-父子组件语法
    vue(一)使用vue-cli搭建项目
    CSS table-layout 属性
    git学习
  • 原文地址:https://www.cnblogs.com/nanfeng-blog/p/15018584.html
Copyright © 2011-2022 走看看