zoukankan      html  css  js  c++  java
  • CF 375D. Tree and Queries加强版!!!【dfs序分块 大小分类讨论】

    传送门

    题意:

    一棵树,询问一个子树内出现次数$ge k$的颜色有几种,Candy?这个沙茶自带强制在线


    吐槽:

    本来一道可以离散的莫队我非要强制在线用分块做;上午就开始写了然后发现思路错了...;改 下午继续写....然后发现看大了数据范围卡空间了...;改 然后又发现好多bug...;再改 然后发现TLE了... ;改块的大小....可恶又卡空间了.... ;改short...可恶溢出了;改unsigned short....可恶n总共才1e5怎么练unsigned short也溢出了.....; 开O2...还不行....;然后发现之前把块的大小和数量搞反了....;继续改块的大小再加上有理有据对本题特性的vector优化.....终于A了.................

    题解:

    一开始想成已经知道k预处理f不用第三维了(md那还用分块干什么)

    对出现次数$>S$和$le S$的分开讨论

    预处理$f[i][j][k]$为块i到块j出现次数$[k,S]$的有几种

    $s[i][j]$为前i块颜色j出现了几次

    询问的时候

    两边不完整的块暴力枚举

    $>S$的部分不超过$frac{N}{S}$种,单独暴力枚举(注意如果两边枚举过了就不能重复枚举了)

    $[k,S]$的部分直接用预处理的f

    #pragma GCC optimize ("O2")
    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #include <cstring>
    #include <cmath>
    #include <vector>
    using namespace std;
    typedef long long ll;
    const int N=1e5+5, M=245, S=425;
    inline int read(){
        char c=getchar();int x=0,f=1;
        while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
        while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
        return x*f;
    }
    
    int n,Q,col,a[N],u,v,k;
    int cou[N], big[N], tot, mark[N];bool biiig[N];
    struct edge{int v,ne;}e[N<<1];
    int cnt,h[N];
    inline void ins(int u,int v){
        e[++cnt]=(edge){v,h[u]}; h[u]=cnt;
        e[++cnt]=(edge){u,h[v]}; h[v]=cnt;
    }
    int dfc,L[N],R[N];
    int t[N];
    void dfs(int u,int fa){
        L[u]=++dfc; a[dfc]=t[u];
        for(int i=h[u];i;i=e[i].ne)
            if(e[i].v!=fa) dfs(e[i].v, u);
        R[u]=dfc;
    }
    
    int block,m,pos[N];
    struct _blo{int l,r;}b[M];
    void ini(){
        //block=sqrt(n); 
        block=420;
        m=(n-1)/block+1;
        for(int i=1;i<=n;i++) pos[i]=(i-1)/block+1;
        for(int i=1;i<=m;i++) b[i].l=(i-1)*block+1, b[i].r=i*block;
        b[m].r=n;
    }
    
    struct Block{
        int f[M][M][S], c[N], s[M][N];
    
        void Set0(int x){
            for(int i=1;i<=col;i++) s[x][i]=s[x-1][i];
            for(int i=b[x].l; i<=b[x].r; i++) s[x][a[i]]++;
        }
    
        void Set1(int x){
            for(int t=x;t<=m;t++){
                for(int i=b[t].l; i<=b[t].r; i++) if(!biiig[ a[i] ]) c[a[i]]++;
                for(int i=b[t].l; i<=b[t].r; i++) if(!biiig[ a[i] ] && c[a[i]]>0){ 
                    int _=s[t-1][a[i]] - s[x-1][a[i]];
                    f[x][t][ _+c[a[i]] ]++;
                    f[x][t][ _ ]--;
                    c[a[i]]=0;
                }
                for(int i=block; i>=1; i--) f[x][t][i]+=f[x][t][i+1];
                for(int i=1; i<=block; i++) f[x][t][i]+=f[x][t-1][i];
            }
        }
    
        int Que(int l,int r,int k){ 
            int pl=pos[l], pr=pos[r];
            int ans=0;
            if(pl==pr){
                for(int i=l; i<=r; i++) c[a[i]]++;
                for(int i=l; i<=r; i++) if(c[a[i]]>0) ans+= c[a[i]]>=k, c[a[i]]=0;
            }else{
                for(int i=1; i<=tot; i++) mark[ big[i] ]=0;
                vector<int> v;
                int *rr=s[pr], *ll=s[pl-1];
                for(int i=l; i<=b[pl].r; i++){ 
                    mark[ a[i] ]=1;
                    if(rr[a[i]] - ll[a[i]]>=k)
                        c[a[i]]++, v.push_back(a[i]); 
                }
                for(int i=b[pr].l; i<=r; i++){
                    mark[ a[i] ]=1;
                    if(rr[a[i]] - ll[a[i]]>=k)
                        c[a[i]]++, v.push_back(a[i]); 
                }
    
                for(int i=0; i<(int)v.size(); i++) if(c[v[i]]>0){
                    int _=s[pr-1][v[i]] - s[pl][v[i]];
                    if(biiig[ v[i] ]) ans+= _+c[v[i]]>=k;
                    else ans+= (_<k && _+c[v[i]]>=k);
                    c[v[i]]=0;
                }
    
                if(k<=block) ans+=f[pl+1][pr-1][k]; 
                for(int i=1;i<=tot;i++) if(!mark[ big[i] ])
                    ans+= s[pr-1][big[i]] - s[pl][big[i]] >= k;
            }
            return ans;
        }
    }B;
    
    int main(){
    //    freopen("in","r",stdin);
        n=read(); Q=read(); ini();
        for(int i=1;i<=n;i++) a[i]=t[i]=read(), col=max(col, a[i]), cou[a[i]]++;
        for(int i=1;i<n;i++) ins(read(), read());
        dfs(1,0);
    
        for(int i=1;i<=col;i++) if(cou[i]>block) big[++tot]=i, biiig[i]=1;
        for(int i=1;i<=m;i++) B.Set0(i);
        for(int i=1;i<=m;i++) B.Set1(i);
    
        while(Q--){
            u=read(); k=read();
            printf("%d
    ", B.Que(L[u], R[u], k) );
        }
    }
  • 相关阅读:
    Asp.net弹出浏览器客户端确认对话框代码 Carlwave
    VS 2005 与SQL Server 2005整合优势在哪里?(from csdn.net) Carlwave
    如何让搜索引擎收录我的站点 Carlwave
    超强扩展性的DNNDotNetNuke模块功能分类列表(from 中国DNN) Carlwave
    DotNetNuke命名空间概述 Carlwave
    Most Popular Questions and Answers on ASP.NET Whidbey(from asp.net forums,write by ASP.NET Team) Carlwave
    火箭官方宣告麦蒂缺阵五周 季后赛前景蒙上阴影 Carlwave
    asp.net有效使用缓存(转) Carlwave
    《Business Rules Engine Overview》《业务规则引擎概述》write by Mark Kamoski Carlwave
    中国详细省市县自治区名称列表(含access数据库和sql2000备份数据库) Carlwave
  • 原文地址:https://www.cnblogs.com/candy99/p/6567213.html
Copyright © 2011-2022 走看看