zoukankan      html  css  js  c++  java
  • 【BZOJ】【3757】苹果树

    树分块

      orz HZWER 

      http://hzwer.com/5259.html

      不知为何我原本写的倍增求LCA给WA了……学习了HZWER的倍增新姿势~

      树上分块的转移看vfk博客的讲解吧……(其实是先指向hzwer博客,再跳转vfk和KuribohG……)

      vfk讲的很详细,重点就在于转移的时候无视lca,只有在计算答案的时候临时加进来lca,算完答案再把lca去掉。

      1 /**************************************************************
      2     Problem: 3757
      3     User: Tunix
      4     Language: C++
      5     Result: Accepted
      6     Time:17180 ms
      7     Memory:17716 kb
      8 ****************************************************************/
      9  
     10 //BZOJ 3757
     11 #include<cmath>
     12 #include<cstdio>
     13 #include<cstring>
     14 #include<cstdlib>
     15 #include<iostream>
     16 #include<algorithm>
     17 #define rep(i,n) for(int i=0;i<n;++i)
     18 #define F(i,j,n) for(int i=j;i<=n;++i)
     19 #define D(i,j,n) for(int i=j;i>=n;--i)
     20 using namespace std;
     21 void read(int &v){
     22     v=0; int sign=1; char ch=getchar();
     23     while(ch<'0'||ch>'9'){ if (ch=='-') sign=-1; ch=getchar();}
     24     while(ch>='0'&&ch<='9'){ v=v*10+ch-'0'; ch=getchar();}
     25     v*=sign;
     26 }
     27 #define debug
     28 /******************tamplate*********************/
     29 const int N=100010;
     30 int head[N],to[N],next[N],cnt;
     31 void add(int x,int y){
     32     to[++cnt]=y; next[cnt]=head[x]; head[x]=cnt;
     33     to[++cnt]=x; next[cnt]=head[y]; head[y]=cnt;
     34 }
     35 /*******************edge************************/
     36 int n,m,color[N],root;
     37 int B,belong[N],st[N],top,tot,deep[N];
     38 int fa[N][20],bin[25];
     39 void dfs(int x){
     40     int bottom=top;
     41     for(int i=1;i<=16;i++)
     42         if(deep[x]>=bin[i])
     43             fa[x][i]=fa[fa[x][i-1]][i-1];
     44         else break;
     45     for(int i=head[x];i;i=next[i])
     46         if (to[i]!=fa[x][0]){
     47             fa[to[i]][0]=x;
     48             deep[to[i]]=deep[x]+1;
     49             dfs(to[i]);
     50             if (top-bottom>=B){
     51                 ++tot;
     52                 while(top!=bottom)
     53                     belong[st[top--]]=tot;
     54             }
     55         }
     56     st[++top]=x;
     57 }
     58 int LCA(int x,int y){
     59     if (deep[x]<deep[y]) swap(x,y);
     60     int t=deep[x]-deep[y];
     61     for(int i=0;bin[i]<=t;i++)
     62         if (t&bin[i]) x=fa[x][i];
     63     D(i,16,0)
     64         if(fa[x][i]!=fa[y][i])
     65             x=fa[x][i],y=fa[y][i];
     66     if(x==y) return x;
     67     return fa[x][0];
     68 }
     69 /*******************dfs&&LCA********************/
     70 struct ques{
     71     int x,y,a,b,num;
     72     bool operator < (const ques &now)const{
     73         if (belong[x]==belong[now.x]) return belong[y]<belong[now.y];
     74         else return belong[x]<belong[now.x];
     75     }
     76 }Q[N];
     77  
     78 int num[N],ans=0,ANS[N];
     79 bool used[N];
     80 inline void work(int x){
     81     if(!used[x]){
     82         num[color[x]]++;used[x]=1;
     83         if(num[color[x]]==1) ans++;
     84     }
     85     else{
     86         num[color[x]]--;used[x]=0;
     87         if(num[color[x]]==0) ans--;
     88     }
     89 }
     90  
     91 void Xor(int x,int y){
     92     int lca=LCA(x,y);
     93     while(x!=lca) {work(x); x=fa[x][0];}
     94     while(y!=lca) {work(y); y=fa[y][0];}
     95 }
     96  
     97 int main(){
     98     bin[0]=1; F(i,1,20) bin[i]=bin[i-1]<<1;
     99  
    100     read(n); read(m);
    101     B=sqrt(n);
    102     F(i,1,n) read(color[i]);
    103     int x,y;
    104     F(i,1,n){
    105         read(x); read(y);
    106         if (x==0) root=y;
    107         if (y==0) root=x;
    108         add(x,y);
    109     }
    110     dfs(root);
    111     tot++;
    112     while(top)belong[st[top--]]=tot;
    113  
    114     int a,b;
    115     F(i,1,m){
    116         read(x); read(y); read(a); read(b);
    117         Q[i]=(ques){x,y,a,b,i};
    118     }
    119     sort(Q+1,Q+m+1);
    120     //转移的时候不考虑LCA,查答案的时候临时算进来,计算完答案后再把LCA删掉
    121     int lca=(LCA(Q[1].x,Q[1].y));
    122     Xor(Q[1].x,Q[1].y);
    123     work(lca);
    124     ANS[Q[1].num]=ans;
    125     if (num[Q[1].a]!=0 && num[Q[1].b]!=0 && Q[1].a!=Q[1].b) ANS[Q[1].num]--;
    126     work(lca);
    127     F(i,2,m){
    128         Xor(Q[i-1].x,Q[i].x);
    129         Xor(Q[i-1].y,Q[i].y);
    130         lca=LCA(Q[i].x,Q[i].y);
    131         work(lca);
    132         ANS[Q[i].num]=ans;
    133         if(num[Q[i].a]!=0 && num[Q[i].b]!=0 && Q[i].a!=Q[i].b) ANS[Q[i].num]--;
    134         work(lca);
    135     }
    136     F(i,1,m) printf("%d
    ",ANS[i]);
    137     return 0;
    138 }
    View Code

    3757: 苹果树

    Time Limit: 20 Sec  Memory Limit: 256 MB
    Submit: 632  Solved: 223
    [Submit][Status][Discuss]

    Description

        神犇家门口种了一棵苹果树。苹果树作为一棵树,当然是呈树状结构,每根树枝连接两个苹果,每个苹果都可以沿着一条由树枝构成的路径连到树根,而且这样的路径只存在一条。由于这棵苹果树是神犇种的,所以苹果都发生了变异,变成了各种各样的颜色。我们用一个到n之间的正整数来表示一种颜色。树上一共有n个苹果。每个苹果都被编了号码,号码为一个1到n之间的正整数。我们用0代表树根。只会有一个苹果直接根。

    有许许多多的人来神犇家里膜拜神犇。可神犇可不是随便就能膜拜的。前来膜拜神犇的人需要正确回答一个问题,才能进屋膜拜神犇。这个问题就是,从树上编号为u的苹果出发,由树枝走到编号为v的苹果,路径上经过的苹果一共有多少种不同的颜色(包括苹果u和苹果v的颜色)?不过神犇注意到,有些来膜拜的人患有色盲症。具体地说,一个人可能会认为颜色a就是颜色b,那么他们在数苹果的颜色时,如果既出现了颜色a的苹果,又出现了颜色b的苹果,这个人只会算入颜色b,而不会把颜色a算进来。

    神犇是一个好人,他不会强人所难,也就会接受由于色盲症导致的答案错误(当然答案在色盲环境下也必须是正确的)。不过这样神犇也就要更改他原先数颜色的程序了。虽然这对于神犇来说是小菜一碟,但是他想考验一下你。你能替神犇完成这项任务吗?

    Input

    输入第一行为两个整数n和m,分别代表树上苹果的个数和前来膜拜的人数。
    接下来的一行包含n个数,第i个数代表编号为i的苹果的颜色Coli。
    接下来有n行,每行包含两个数x和y,代表有一根树枝连接了苹果x和y(或者根和一个苹果)。
    接下来有m行,每行包含四个整数u、v、a和b,代表这个人要数苹果u到苹果v的颜色种数,同时这个人认为颜色a就是颜色b。如果a=b=0,则代表这个人没有患色盲症。

    Output

    输出一共m行,每行仅包含一个整数,代表这个人应该数出的颜色种数。

    Sample Input

    5 3
    1 1 3 3 2
    0 1
    1 2
    1 3
    2 4
    3 5
    1 4 0 0
    1 4 1 3
    1 4 1 2

    Sample Output

    2
    1
    2

    HINT

    0<=x,y,a,b<=N

    N<=50000

    1<=U,V,Coli<=N

    Source

    [Submit][Status][Discuss]
  • 相关阅读:
    hdu 4297 One and One Story 夜
    hdu 4280 Island Transport 夜
    1389. Roadworks 夜
    hdu 4289 Control 夜
    hdu 4291 A Short problem 夜
    hdu 4284 Travel 夜
    1080. Map Coloring 夜
    正则中的转义符\
    起重复出现作用的量词*和+
    安卓的权限大全和动态使用安卓权限
  • 原文地址:https://www.cnblogs.com/Tunix/p/4249215.html
Copyright © 2011-2022 走看看