bzoj 3757: 苹果树

树分块,然后莫队,不知道为什么RE了,挖坑++

为了处理由一个转移到下一个,(莫队嘛),要做的就是把上次询问的左端点s1,和这次询问的左端点s2,求lca,然后把路径上的操作去反,右端点一样的。

为什么对,有神犇用公式证明的,然后本蒟蒻画了个草图,一看就很显然2333,但是根节点还是不显然的,,,(还是能将就着看的233)

  1 #include<bits/stdc++.h>
  2 #define N 1000005
  3 #define LL long long
  4 #define inf 0x3f3f3f3f
  5 using namespace std;
  6 inline int ra()
  7 {
  8     int x=0,f=1; char ch=getchar();
  9     while (ch<'0' || ch>'9') {if (ch=='-') f=-1; ch=getchar();}
 10     while (ch>='0' && ch<='9') {x=x*10+ch-'0'; ch=getchar();}
 11     return x*f;
 12 }
 13 int bin[20];
 14 int n,m,cnt,ans1;
 15 int top,ind,block,blocknum,root;
 16 int ans[100005],p[100005];
 17 int fa[100005][20],deep[100005];
 18 int c[100005],st[100005],dfn[100005],belong[100005];
 19 bool vis[100005];
 20 struct data{int to,next;}e[200005];
 21 int head[100005];
 22 struct query{int x,y,a,b,id;}q[200005];
 23 bool operator < (query a, query b){
 24     if (belong[a.x]==belong[b.x]) return dfn[a.y]<dfn[b.y];
 25     return belong[a.x]<belong[b.x];
 26 }
 27 void insert(int x, int y) {e[++cnt].next=head[x]; e[cnt].to=y; head[x]=cnt;}
 28 int dfs(int x)
 29 {
 30     int size=0;
 31     dfn[x]=++ind;
 32     for (int i=1; i<=18; i++)
 33         if (deep[x]>=bin[i])
 34             fa[x][i]=fa[fa[x][i-1]][i-1];
 35         else break;
 36     for (int i=head[x];i;i=e[i].next)
 37         if (e[i].to!=fa[x][0])
 38         {
 39             deep[e[i].to]=deep[x]+1;
 40             fa[e[i].to][0]=x;
 41             size+=dfs(e[i].to);
 42             if (size>=block) 
 43             {
 44                 blocknum++;
 45                 for (int k=1; k<=size; k++)
 46                     belong[st[top--]]=blocknum;
 47                 size=0;
 48             }
 49         }
 50     st[++top]=x;
 51     return size+1;
 52 }
 53 int lca(int x, int y)
 54 {
 55     if (deep[x]<deep[y]) swap(x,y);
 56     int t=deep[x]-deep[y];
 57     for (int i=0; bin[i]<=t; i++)
 58         if (t&bin[i]) x=fa[x][i];
 59     for (int i=18; i>=0; i--)
 60         if (fa[x][i]!=fa[y][i])
 61             x=fa[x][i],y=fa[y][i];
 62     if (x==y) return x;
 63     return fa[x][0];
 64 }
 65 void rever(int x)
 66 {
 67     if (!vis[x]) {vis[x]=1; p[c[x]]++; if (p[c[x]]==1) ans1++;}
 68     else {vis[x]=0; p[c[x]]--; if (p[c[x]]==0) ans1--;}
 69 }
 70 void solve(int x, int y)
 71 {
 72     while (x!=y)
 73         if (deep[x]>deep[y]) rever(x),x=fa[x][0];
 74         else rever(y),y=fa[y][0];
 75 }
 76 int main()
 77 {
 78     bin[0]=1; for (int i=1; i<20; i++) bin[i]=bin[i-1]<<1;
 79     n=ra(); m=ra();
 80     block=sqrt(n);
 81     for (int i=1; i<=n; i++) c[i]=ra();
 82     for (int i=1; i<=n; i++)
 83     {
 84         int x=ra(),y=ra();
 85         if (!x) root=y;
 86         else if (!y) root=x;
 87         else insert(x,y),insert(y,x);
 88     }
 89     dfs(root); blocknum++;
 90     while (top) belong[st[top--]]=blocknum;
 91     for (int i=1; i<=m; i++)
 92     {
 93         q[i].x=ra(),q[i].y=ra();
 94         if (dfn[q[i].x]>dfn[q[i].y]) swap(q[i].x,q[i].y);
 95         q[i].a=ra(); q[i].b=ra(); q[i].id=i;
 96     }
 97     sort(q+1,q+m+1);
 98     int t=lca(q[1].x,q[1].y);
 99     solve(q[1].x,q[1].y); rever(t);
100     ans[q[1].id]=ans1;
101     if (p[q[1].a] && p[q[1].b] && q[1].a!=q[1].b) ans[q[1].id]--;
102     rever(t);
103     for (int i=2; i<=m; i++)
104     {
105         solve(q[i-1].x,q[i].x);
106         solve(q[i-1].y,q[i].y);
107         int t=lca(q[i].x,q[i].y);
108         rever(t);
109         ans[q[i].id]=ans1;
110         if (p[q[i].a] && p[q[i].b] && q[i].a!=q[i].b) ans[q[i].id]--;
111         rever(t);
112     }
113     for (int i=1; i<=m; i++) printf("%d\n",ans[i]);
114     return 0; 
115 }

 

posted @ 2017-02-23 21:36  ws_ccd  阅读(182)  评论(0编辑  收藏  举报