zoukankan      html  css  js  c++  java
  • 「CF375D Tree and Queries」

    题目

    (dsu on tree)的板子题了

    (dsu on tree)本质上一种优秀通过轻重链剖分优化到(O(nlogn))的暴力

    一般用来解决没有修改的允许离线的子树查询问题

    首先先来处理出每一个节点的重儿子

    接下来按照如下的顺序统计

    1. 递归处理当前节点的所有轻儿子

    2. 递归处理重儿子

    3. 遍历一遍整棵子树,统计信息(但是不用访问当前点的重儿子)

    4. 如果这个节点是重儿子,就返回,否则的话就清空所有信息

    所以第三步,不用访问当前点的重儿子就是因为在第四步的时候重儿子没有被清空

    至于这道题我们数颜色的时候开一个树状数组,每次存储颜色的桶数量发生变化,就在树状数组里修改相应的位置

    查一个后缀和就好了

    代码

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define LL long long
    #define re register
    #define lowbit(x) ((x)&(-x))
    #define maxn 100005
    inline int read() {
        int x=0;char c=getchar();while(c<'0'||c>'9') c=getchar();
        while(c>='0'&&c<='9') x=(x<<3)+(x<<1)+c-48,c=getchar();return x;
    }
    int n,m,num,__,Son,tot;
    struct Ask{int x,k,rk;}q[maxn];
    struct E{int v,nxt;}e[maxn<<1];
    int son[maxn],sum[maxn],deep[maxn],col[maxn];
    int dfn[maxn],c[maxn],tax[maxn],Ans[maxn],head[maxn];
    inline int cmp(Ask A,Ask B) {return dfn[A.x]<dfn[B.x];}
    inline void C(int x,int y) {e[++num].v=y;e[num].nxt=head[x];head[x]=num;}
    inline void add(int x,int val) {for(re int i=x;i;i-=lowbit(i)) c[i]+=val;}
    inline int ask(int x) {int now=0;for(re int i=x;i<=n;i+=lowbit(i)) now+=c[i];return now;}
    void dfs1(int x) {
        sum[x]=1;int maxx=-1;
        for(re int i=head[x];i;i=e[i].nxt) {
            if(deep[e[i].v]) continue;
            deep[e[i].v]=deep[x]+1,dfs1(e[i].v);
            sum[x]+=sum[e[i].v];
            if(sum[e[i].v]>maxx) maxx=sum[e[i].v],son[x]=e[i].v;
        }
    }
    void dfs2(int x) {
        for(re int i=head[x];i;i=e[i].nxt)
            if(deep[e[i].v]>deep[x]&&son[x]!=e[i].v) dfs2(e[i].v);
        if(son[x]) dfs2(son[x]);
        dfn[x]=++__;
    }
    void calc(int x,int opt) {
        if(tax[col[x]]) add(tax[col[x]],-1);
        tax[col[x]]+=opt;
        if(tax[col[x]]) add(tax[col[x]],1);
        for(re int i=head[x];i;i=e[i].nxt)
            if(deep[e[i].v]>deep[x]&&Son!=e[i].v) calc(e[i].v,opt);
    }
    void dfs(int x,int opt) {
        for(re int i=head[x];i;i=e[i].nxt) 
        if(deep[e[i].v]>deep[x]&&son[x]!=e[i].v) 
            dfs(e[i].v,0);
        if(son[x]) dfs(son[x],1);
        Son=son[x];calc(x,1);Son=0;
        while(q[tot].x==x) {
            Ans[q[tot].rk]=ask(q[tot].k);tot++;
        }
        if(!opt) calc(x,-1);
    }
    int main() {
        n=read(),m=read();
        for(re int i=1;i<=n;i++) col[i]=read();
        for(re int x,y,i=1;i<n;i++) x=read(),y=read(),C(x,y),C(y,x);
        deep[1]=1,dfs1(1),dfs2(1);
        for(re int i=1;i<=m;i++) q[i].rk=i,q[i].x=read(),q[i].k=read();
        std::sort(q+1,q+m+1,cmp);tot=1;dfs(1,1);
        for(re int i=1;i<=m;i++) printf("%d
    ",Ans[i]);
        return 0;
    }
    
  • 相关阅读:
    win7 配置DNS
    链表效率
    链表用途&&数组效率&&链表效率&&链表优缺点
    java 生成随机数字
    汉诺塔
    利用HTML5开发Android(1)---Android设备多分辨率的问题
    Android读取assets目录下的资源
    Ubuntu 搭建PHP开发环境
    关于heritrix安装配置时出现”必须限制口令文件读取访问权限”的解决方法
    JQuery 的bind和unbind函数
  • 原文地址:https://www.cnblogs.com/asuldb/p/10473422.html
Copyright © 2011-2022 走看看