zoukankan      html  css  js  c++  java
  • BZOJ3757: 苹果树

    题目:http://www.lydsy.com/JudgeOnline/problem.php?id=3757

    题解:

    颜色种数不太好用树形数据结构维护,因为子节点的信息不能快速合并为父节点的信息。而莫队算法正是解决这类题目的利器。

    节点与节点间的转移可以戳vfleaking的blog:http://vfleaking.blog.163.com/blog/static/174807634201311011201627/

    比较巧妙的一点是把麻烦的lca去掉,然后统计答案的时候加上,统计完了再删去。

    其实我做这题是为了测试各种树分块的快慢。。。

    #1 按王室联邦的分块方法,可以保证所有的块内距离<=sqrt(n),最多有一块的大小>sqrt(n)并且<3sqrt(n)。块内可能是不连通的。

        但这对我们算法的执行并没有什么影响,因为它只是作为莫队算法排序的参照(可以说是估价函数)。

        块大小sqrt(n) 耗时 8744ms

        块大小sqrt(n*log2(n)) 耗时 7520ms

      1 #include<cstdio>
      2 
      3 #include<cstdlib>
      4 
      5 #include<cmath>
      6 
      7 #include<cstring>
      8 
      9 #include<algorithm>
     10 
     11 #include<iostream>
     12 
     13 #include<vector>
     14 
     15 #include<map>
     16 
     17 #include<set>
     18 
     19 #include<queue>
     20 
     21 #include<string>
     22 
     23 #define inf 1000000000
     24 
     25 #define maxn 200000+5
     26 
     27 #define maxm 200000+5
     28 
     29 #define eps 1e-10
     30 
     31 #define ll long long
     32 
     33 #define pa pair<int,int>
     34 
     35 #define for0(i,n) for(int i=0;i<=(n);i++)
     36 
     37 #define for1(i,n) for(int i=1;i<=(n);i++)
     38 
     39 #define for2(i,x,y) for(int i=(x);i<=(y);i++)
     40 
     41 #define for3(i,x,y) for(int i=(x);i>=(y);i--)
     42 
     43 #define for4(i,x) for(int i=head[x],y=e[i].go;i;i=e[i].next,y=e[i].go)
     44 
     45 #define for5(n,m) for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)
     46 
     47 #define mod 1000000007
     48 
     49 using namespace std;
     50 
     51 inline int read()
     52 
     53 {
     54 
     55     int x=0,f=1;char ch=getchar();
     56 
     57     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
     58 
     59     while(ch>='0'&&ch<='9'){x=10*x+ch-'0';ch=getchar();}
     60 
     61     return x*f;
     62 
     63 }
     64 int n,m,size,top,cnt,tot,rt,ti,ret;
     65 int a[maxn],head[maxn],ans[maxn],s[maxn],b[maxn],pos[maxn],sta[maxn],f[maxn][18],dep[maxn];
     66 struct rec{int l,r,x,y,id;}q[maxn];
     67 struct edge{int go,next;}e[2*maxn];
     68 bool v[maxn];
     69 inline void add(int x,int y)
     70 {
     71     e[++tot]=(edge){y,head[x]};head[x]=tot;
     72     e[++tot]=(edge){x,head[y]};head[y]=tot;
     73 }
     74 inline void dfs(int x)
     75 {
     76     pos[x]=++ti;int tmp=top;
     77     for1(i,17)if(dep[x]>=1<<i)f[x][i]=f[f[x][i-1]][i-1];else break;
     78     for4(i,x)if(y!=f[x][0])
     79     {
     80         f[y][0]=x;dep[y]=dep[x]+1;
     81         dfs(y);
     82         if(top-tmp>=size)
     83         {
     84             ++cnt;
     85             while(top!=tmp)b[sta[top--]]=cnt;
     86         }
     87     }
     88     sta[++top]=x;
     89 }
     90 inline int lca(int x,int y)
     91 {
     92     if(dep[x]<dep[y])swap(x,y);
     93     int t=dep[x]-dep[y];
     94     for0(i,17)if(t&(1<<i))x=f[x][i];
     95     if(x==y)return x;
     96     for3(i,17,0)if(f[x][i]!=f[y][i])x=f[x][i],y=f[y][i];
     97     return f[x][0];
     98 }
     99 inline void change(int x)
    100 {
    101     if(v[x]){s[a[x]]--;if(!s[a[x]])ret--;}
    102     else {s[a[x]]++;if(s[a[x]]==1)ret++;}
    103     v[x]^=1;
    104 }
    105 inline void work(int x,int y)
    106 {
    107     while(x!=y)
    108     {
    109         if(dep[x]<dep[y])swap(x,y);
    110         change(x);
    111         x=f[x][0];
    112     }
    113 }
    114 inline bool cmp(rec x,rec y){return b[x.l]==b[y.l]?pos[x.r]<pos[y.r]:b[x.l]<b[y.l];}
    115 
    116 int main()
    117 
    118 {
    119 
    120     freopen("input.txt","r",stdin);
    121 
    122     freopen("output.txt","w",stdout);  
    123     n=read();m=read();
    124     for1(i,n)a[i]=read();
    125     for1(i,n){int x=read(),y=read();add(x,y);if(x*y==0)rt=x+y;}
    126     size=sqrt(n);
    127     dfs(rt);
    128     while(top)b[sta[top--]]=cnt;
    129     for1(i,m)
    130     {
    131         q[i].l=read(),q[i].r=read(),q[i].x=read(),q[i].y=read(),q[i].id=i;
    132         if(b[q[i].l]>b[q[i].r])swap(q[i].l,q[i].r);
    133     }
    134     sort(q+1,q+m+1,cmp);
    135     int l=rt,r=rt;
    136     for1(i,m)
    137     {
    138         work(l,q[i].l);work(r,q[i].r);
    139         l=q[i].l;r=q[i].r;int f=lca(l,r);
    140         change(f);
    141         ans[q[i].id]=ret-(int)(q[i].x!=q[i].y&&s[q[i].x]&&s[q[i].y]);
    142         change(f);
    143     }
    144     for1(i,m)printf("%d
    ",ans[i]);
    145 
    146     return 0;
    147 
    148 }  
    View Code

    #2 按照块状树的分块方法,如果一个节点父节点所在块的大小还没有达到sqrt(n),就把该点塞入父亲所在块,否则另开一块。

         这样可以保证块内的所有点都是连通的。但是由于是从上到下分,所以会被菊花图卡到块数为O(n)

         块大小sqrt(n) 耗时 9448ms

         块大小sqrt(n*log2(n)) 耗时 7180ms

      1 #include<cstdio>
      2 
      3 #include<cstdlib>
      4 
      5 #include<cmath>
      6 
      7 #include<cstring>
      8 
      9 #include<algorithm>
     10 
     11 #include<iostream>
     12 
     13 #include<vector>
     14 
     15 #include<map>
     16 
     17 #include<set>
     18 
     19 #include<queue>
     20 
     21 #include<string>
     22 
     23 #define inf 1000000000
     24 
     25 #define maxn 200000+5
     26 
     27 #define maxm 200000+5
     28 
     29 #define eps 1e-10
     30 
     31 #define ll long long
     32 
     33 #define pa pair<int,int>
     34 
     35 #define for0(i,n) for(int i=0;i<=(n);i++)
     36 
     37 #define for1(i,n) for(int i=1;i<=(n);i++)
     38 
     39 #define for2(i,x,y) for(int i=(x);i<=(y);i++)
     40 
     41 #define for3(i,x,y) for(int i=(x);i>=(y);i--)
     42 
     43 #define for4(i,x) for(int i=head[x],y=e[i].go;i;i=e[i].next,y=e[i].go)
     44 
     45 #define for5(n,m) for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)
     46 
     47 #define mod 1000000007
     48 
     49 using namespace std;
     50 
     51 inline int read()
     52 
     53 {
     54 
     55     int x=0,f=1;char ch=getchar();
     56 
     57     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
     58 
     59     while(ch>='0'&&ch<='9'){x=10*x+ch-'0';ch=getchar();}
     60 
     61     return x*f;
     62 
     63 }
     64 int n,m,size,top,cnt,tot,rt,ti,ret;
     65 int a[maxn],head[maxn],sum[maxn],ans[maxn],s[maxn],b[maxn],pos[maxn],sta[maxn],f[maxn][18],dep[maxn];
     66 struct rec{int l,r,x,y,id;}q[maxn];
     67 struct edge{int go,next;}e[2*maxn];
     68 bool v[maxn];
     69 inline void add(int x,int y)
     70 {
     71     e[++tot]=(edge){y,head[x]};head[x]=tot;
     72     e[++tot]=(edge){x,head[y]};head[y]=tot;
     73 }
     74 inline void dfs(int x)
     75 {
     76     pos[x]=++ti;
     77     for1(i,17)if(dep[x]>=1<<i)f[x][i]=f[f[x][i-1]][i-1];else break;
     78     for4(i,x)if(y!=f[x][0])
     79     {
     80         f[y][0]=x;dep[y]=dep[x]+1;
     81         sum[b[y]=sum[b[x]]<size?b[x]:++cnt]++;
     82         dfs(y);
     83     }
     84 }
     85 inline int lca(int x,int y)
     86 {
     87     if(dep[x]<dep[y])swap(x,y);
     88     int t=dep[x]-dep[y];
     89     for0(i,17)if(t&(1<<i))x=f[x][i];
     90     if(x==y)return x;
     91     for3(i,17,0)if(f[x][i]!=f[y][i])x=f[x][i],y=f[y][i];
     92     return f[x][0];
     93 }
     94 inline void change(int x)
     95 {
     96     if(v[x]){s[a[x]]--;if(!s[a[x]])ret--;}
     97     else {s[a[x]]++;if(s[a[x]]==1)ret++;}
     98     v[x]^=1;
     99 }
    100 inline void work(int x,int y)
    101 {
    102     while(x!=y)
    103     {
    104         if(dep[x]<dep[y])swap(x,y);
    105         change(x);
    106         x=f[x][0];
    107     }
    108 }
    109 inline bool cmp(rec x,rec y){return b[x.l]==b[y.l]?pos[x.r]<pos[y.r]:b[x.l]<b[y.l];}
    110 
    111 int main()
    112 
    113 {
    114 
    115     freopen("input.txt","r",stdin);
    116 
    117     freopen("output.txt","w",stdout);  
    118     n=read();m=read();
    119     for1(i,n)a[i]=read();
    120     for1(i,n){int x=read(),y=read();add(x,y);if(x*y==0)rt=x+y;}
    121     size=sqrt(n);
    122     sum[1]=b[1]=cnt=1;
    123     dfs(rt);
    124     for1(i,m)
    125     {
    126         q[i].l=read(),q[i].r=read(),q[i].x=read(),q[i].y=read(),q[i].id=i;
    127         if(b[q[i].l]>b[q[i].r])swap(q[i].l,q[i].r);
    128     }
    129     sort(q+1,q+m+1,cmp);
    130     int l=rt,r=rt;
    131     for1(i,m)
    132     {
    133         work(l,q[i].l);work(r,q[i].r);
    134         l=q[i].l;r=q[i].r;int f=lca(l,r);
    135         change(f);
    136         ans[q[i].id]=ret-(int)(q[i].x!=q[i].y&&s[q[i].x]&&s[q[i].y]);
    137         change(f);
    138     }
    139     for1(i,m)printf("%d
    ",ans[i]);
    140 
    141     return 0;
    142 
    143 }  
    View Code

    #3 直接把dfs序拉出来,做序列上的分块。这样有可能块内两点之间离了很远。感觉效果不会很好,但是好写。。。

        耗时 16800ms

      1 #include<cstdio>
      2 
      3 #include<cstdlib>
      4 
      5 #include<cmath>
      6 
      7 #include<cstring>
      8 
      9 #include<algorithm>
     10 
     11 #include<iostream>
     12 
     13 #include<vector>
     14 
     15 #include<map>
     16 
     17 #include<set>
     18 
     19 #include<queue>
     20 
     21 #include<string>
     22 
     23 #define inf 1000000000
     24 
     25 #define maxn 200000+5
     26 
     27 #define maxm 200000+5
     28 
     29 #define eps 1e-10
     30 
     31 #define ll long long
     32 
     33 #define pa pair<int,int>
     34 
     35 #define for0(i,n) for(int i=0;i<=(n);i++)
     36 
     37 #define for1(i,n) for(int i=1;i<=(n);i++)
     38 
     39 #define for2(i,x,y) for(int i=(x);i<=(y);i++)
     40 
     41 #define for3(i,x,y) for(int i=(x);i>=(y);i--)
     42 
     43 #define for4(i,x) for(int i=head[x],y=e[i].go;i;i=e[i].next,y=e[i].go)
     44 
     45 #define for5(n,m) for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)
     46 
     47 #define mod 1000000007
     48 
     49 using namespace std;
     50 
     51 inline int read()
     52 
     53 {
     54 
     55     int x=0,f=1;char ch=getchar();
     56 
     57     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
     58 
     59     while(ch>='0'&&ch<='9'){x=10*x+ch-'0';ch=getchar();}
     60 
     61     return x*f;
     62 
     63 }
     64 int n,m,size,top,cnt,tot,rt,ti,ret;
     65 int a[maxn],head[maxn],sum[maxn],ans[maxn],s[maxn],b[maxn],pos[maxn],sta[maxn],f[maxn][18],dep[maxn];
     66 struct rec{int l,r,x,y,id;}q[maxn];
     67 struct edge{int go,next;}e[2*maxn];
     68 bool v[maxn];
     69 inline void add(int x,int y)
     70 {
     71     e[++tot]=(edge){y,head[x]};head[x]=tot;
     72     e[++tot]=(edge){x,head[y]};head[y]=tot;
     73 }
     74 inline void dfs(int x)
     75 {
     76     pos[x]=++ti;
     77     for1(i,17)if(dep[x]>=1<<i)f[x][i]=f[f[x][i-1]][i-1];else break;
     78     for4(i,x)if(y!=f[x][0])
     79     {
     80         f[y][0]=x;dep[y]=dep[x]+1;
     81         dfs(y);
     82     }
     83 }
     84 inline int lca(int x,int y)
     85 {
     86     if(dep[x]<dep[y])swap(x,y);
     87     int t=dep[x]-dep[y];
     88     for0(i,17)if(t&(1<<i))x=f[x][i];
     89     if(x==y)return x;
     90     for3(i,17,0)if(f[x][i]!=f[y][i])x=f[x][i],y=f[y][i];
     91     return f[x][0];
     92 }
     93 inline void change(int x)
     94 {
     95     if(v[x]){s[a[x]]--;if(!s[a[x]])ret--;}
     96     else {s[a[x]]++;if(s[a[x]]==1)ret++;}
     97     v[x]^=1;
     98 }
     99 inline void work(int x,int y)
    100 {
    101     while(x!=y)
    102     {
    103         if(dep[x]<dep[y])swap(x,y);
    104         change(x);
    105         x=f[x][0];
    106     }
    107 }
    108 inline bool cmp(rec x,rec y){return b[pos[x.l]]==b[pos[y.l]]?pos[x.r]<pos[y.r]:b[pos[x.l]]<b[pos[y.l]];}
    109 
    110 int main()
    111 
    112 {
    113 
    114     freopen("input.txt","r",stdin);
    115 
    116     freopen("output.txt","w",stdout);  
    117     n=read();m=read();
    118     for1(i,n)a[i]=read();
    119     for1(i,n){int x=read(),y=read();add(x,y);if(x*y==0)rt=x+y;}
    120     size=sqrt(n);
    121     dfs(rt);
    122     for1(i,n)b[i]=(i-1)/size+1;
    123     for1(i,m)
    124     {
    125         q[i].l=read(),q[i].r=read(),q[i].x=read(),q[i].y=read(),q[i].id=i;
    126         if(b[q[i].l]>b[q[i].r])swap(q[i].l,q[i].r);
    127     }
    128     sort(q+1,q+m+1,cmp);
    129     int l=rt,r=rt;
    130     for1(i,m)
    131     {
    132         work(l,q[i].l);work(r,q[i].r);
    133         l=q[i].l;r=q[i].r;int f=lca(l,r);
    134         change(f);
    135         ans[q[i].id]=ret-(int)(q[i].x!=q[i].y&&s[q[i].x]&&s[q[i].y]);
    136         change(f);
    137     }
    138     for1(i,m)printf("%d
    ",ans[i]);
    139 
    140     return 0;
    141 
    142 }  
    View Code

    按dfs序分块果然是做死。。。七爷有更好的办法?

    从此AC率是路人T_T

       

      

  • 相关阅读:
    执行上下文和作用域,作用域链
    学习笔记一:定位
    exports和module.exports的区别——学习笔记
    伪类和伪元素
    visibility和display
    CSS选择器,层叠
    Servlet乱码处理-------续集
    Servlet的乱码处理手记
    前端框架之Semantic UI
    最完整的Oracle11g 概述
  • 原文地址:https://www.cnblogs.com/zyfzyf/p/4250029.html
Copyright © 2011-2022 走看看