• BZOJ3351 [ioi2009]Regions


    https://www.cnblogs.com/cutemush/p/12797280.html

    给定一棵有根树,每次询问所有颜色为a的节点的子树中颜色为b的节点个数之和。

     思路:

    考虑将询问按b的出现次数分类。

    若b<=sqrt(n),我们可以在每个b节点用一个vector记录它涉及到的询问。

    dfs,用桶记录从根节点到这个节点每种颜色的出现次数,就可以更新答案了。

    由于总点数为O(q*sqrt(n)),时间复杂度为O(q*sqrt(n))

    若b>sqrt(n),那么只有不超过sqrt(n)种这样的颜色,我们可以在每个a节点用一个vector记录它涉及到的询问。

    dfs,用桶记录子树中各颜色出现次数,更新答案。时间复杂度为O(n*sqrt(n))

    所以总时间复杂度为O(q*sqrt(n)+n*sqrt(n))

    具体看代码

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<vector>
    #include<cmath>
    #include<map>
    using namespace std;
    inline char nc(){
      static char buf[100000],*p1=buf,*p2=buf;
      if(p1==p2){
        p2=(p1=buf)+fread(buf,1,100000,stdin);
        if(p1==p2)return EOF;
      }
      return *p1++;
    }
    inline void Read(int& x){
      char c=nc();
      for(;c<'0'||c>'9';c=nc());
      for(x=0;c>='0'&&c<='9';x=(x<<3)+(x<<1)+c-48,c=nc());
    }
    #define N 200010
    #define R 25010
    #define ll long long
    struct Node
    {
      int x,y;
      Node(){}
      Node(int x,int y):x(x),y(y){}
      bool operator<(Node a)const
      {
        return x<a.x||(x==a.x&&y<a.y);
      }
    }b[N];
    map<Node,int>M;
    vector<int>g[N],B[N],A[N];
    int n,r,q,f[N],a[N],S,Tmp[R],Sum[R],i,F[N];
    ll Ans[N];
    inline void Dfs1(int x)
    {
      Tmp[a[x]]++;
      for(int i=0;i<B[a[x]].size();i++)
          Ans[B[a[x]][i]]+=Tmp[b[B[a[x]][i]].x];
      for(int i=0;i<g[x].size();i++)
          Dfs1(g[x][i]);
      Tmp[a[x]]--;
    }
    inline void Dfs2(int x)
    {
      for(int i=0;i<A[a[x]].size();i++)
        Ans[A[a[x]][i]]-=Tmp[b[A[a[x]][i]].y];
      Tmp[a[x]]++;
      for(int i=0;i<g[x].size();i++)
          Dfs2(g[x][i]);
      for(int i=0;i<A[a[x]].size();i++)
        Ans[A[a[x]][i]]+=Tmp[b[A[a[x]][i]].y];
    }
    char s[30];
    int Len;
    inline void Print(ll x){
      if(x==0)putchar(48);
      for(Len=0;x;x/=10)s[++Len]=x%10;
      for(;Len;)putchar(s[Len--]+48);
      putchar('
    ');
    }
    int main()
    {
      Read(n);Read(r);Read(q);
      S=(int)sqrt((double)n)+1;
      Read(a[1]);
      Sum[a[1]]++;
      for(i=2;i<=n;i++)
          Read(f[i]),
          g[f[i]].push_back(i),
          Read(a[i]),
          Sum[a[i]]++;
      for(i=1;i<=q;i++)
      {
        Read(b[i].x);
    	Read(b[i].y);
    	F[i]=i;
        if(M.count(Node(b[i].x,b[i].y)))
    	    F[i]=M[Node(b[i].x,b[i].y)];
    	else
    	{
          M[Node(b[i].x,b[i].y)]=i;
          if  (Sum[b[i].y]<=S)
          //若b<=sqrt(n),我们可以在每个b节点用一个vector记录它涉及到的询问。
          //dfs,用桶记录从根节点到这个节点每种颜色的出现次数,就可以更新答案了。
    	       B[b[i].y].push_back(i);
    	  else 
    	  //若b>sqrt(n),那么只有不超过sqrt(n)种这样的颜色,
    	  //我们可以在每个a节点用一个vector记录它涉及到的询问。
          //dfs,用桶记录子树中各颜色出现次数,更新答案。时间复杂度为O(n*sqrt(n))
    	       A[b[i].x].push_back(i);
        }
      }
      Dfs1(1);
      Dfs2(1);
      for(i=1;i<=q;i++)
          Print(Ans[F[i]]);
      return 0;
    }
    

      

  • 相关阅读:
    OAuth 2.0之授权码模式
    Rest和Restful & http
    HTTP1.1协议中文版-RFC2616
    Linux中安装Python2.7
    CvMat、Mat、IplImage之间的转换详解及实例
    ROS Node/Topic/Message/Service的一些问题
    ROS的tf_tree相关
    机器人路径规划(包括行人检测及动态避障总结)(长期更新)
    相关博客链接(长期更新)
    关于视觉里程计以及VI融合的相关研究(长期更新)
  • 原文地址:https://www.cnblogs.com/cutemush/p/12797280.html
Copyright © 2020-2023  润新知