BZOJ 3757 苹果树
2017-02-26 19:23
176 查看
题意
神犇家门口种了一棵苹果树。苹果树作为一棵树,当然是呈树状结构,每根树枝连接两个苹果,每个苹果都可以沿着一条由树枝构成的路径连到树根,而且这样的路径只存在一条。由于这棵苹果树是神犇种的,所以苹果都发生了变异,变成了各种各样的颜色。我们用一个到n之间的正整数来表示一种颜色。树上一共有n个苹果。每个苹果都被编了号码,号码为一个1到n之间的正整数。我们用0代表树根。只会有一个苹果直接根。
有许许多多的人来神犇家里膜拜神犇。可神犇可不是随便就能膜拜的。前来膜拜神犇的人需要正确回答一个问题,才能进屋膜拜神犇。这个问题就是,从树上编号为u的苹果出发,由树枝走到编号为v的苹果,路径上经过的苹果一共有多少种不同的颜色(包括苹果u和苹果v的颜色)?不过神犇注意到,有些来膜拜的人患有色盲症。具体地说,一个人可能会认为颜色a就是颜色b,那么他们在数苹果的颜色时,如果既出现了颜色a的苹果,又出现了颜色b的苹果,这个人只会算入颜色b,而不会把颜色a算进来。
神犇是一个好人,他不会强人所难,也就会接受由于色盲症导致的答案错误(当然答案在色盲环境下也必须是正确的)。不过这样神犇也就要更改他原先数颜色的程序了。虽然这对于神犇来说是小菜一碟,但是他想考验一下你。你能替神犇完成这项任务吗?
解
树上莫队
(只跟别人标程拍过了,bzoj交不了)附上数据生成器
#include<cstdio> #include<cstring> #include<algorithm> #include<ctime> #include<cstdlib> #define For(i,j,k) for(int i=(j);i<=(int)k;i++) #define Forr(i,j,k) for(int i=(j);i>=(int)k;i--) using namespace std; int main(){ int n=50000,m=100000; freopen("bzoj3575.in","w",stdout); printf("%d %d\n",n,m); For(i,1,n)printf("%d ",rand()%n+1); puts("0 1"); For(i,2,n){ int u=rand()%(i-1)+1; printf("%d %d\n",i,u); } For(i,1,m){ int u=rand()%n+1,v=rand()%n+1; int a=rand()%n+1,b=rand()%n+1; printf("%d %d %d %d \n",u,v,a,b); } return 0; }
代码
#include<cstdio> #include<cstring> #include<algorithm> #include<cstdlib> #include<cmath> #include<queue> #define For(i,j,k) for(int i=(j);i<=(int)k;i++) #define Forr(i,j,k) for(int i=(j);i>=(int)k;i--) #define Set(a,b) memset(a,b,sizeof(a)) #define ll long long #define Rep(i,u) for(int i=Begin[u],v=to[i];i;i=Next[i],v=to[i]) using namespace std; const int N=50010,INF=0x3f3f3f3f; inline void read(int &x){ x=0;char c=getchar();int f(0); while(c<'0'||c>'9')f|=(c=='-'),c=getchar(); while(c>='0'&&c<='9')x=(x<<1)+(x<<3)+(c^48),c=getchar(); x=f?-x:x; } int Begin ,to[N<<1],Next[N<<1],e,col ,ans,n,m; int dfn ,p ,blo,cnt,blon,rt; inline void add(int x,int y){ to[++e]=y,Next[e]=Begin[x],Begin[x]=e; } struct Tree{ int fa [18],dep ,st ,top; Tree(){top=0;} inline int dfs(int u){ int s=0; dfn[u]=++cnt; Rep(i,u) if(!dep[v]){ dep[v]=dep[u]+1,fa[v][0]=u,s+=dfs(v); if(s>=blo){ blon++; For(j,1,s)p[st[top--]]=blon; s=0; } } st[++top]=u; return s+1; } inline void init(){ For(i,1,17) For(j,1,n) fa[j][i]=fa[fa[j][i-1]][i-1]; } inline int query(int x,int y){ if(dep[x]<dep[y])swap(x,y); int d=dep[x]-dep[y]; for(int i=0;(1<<i)<=d;i++) if(d&(1<<i))x=fa[x][i]; if(x==y)return x; Forr(i,17,0) if(fa[x][i]!=fa[y][i]) x=fa[x][i],y=fa[y][i]; return fa[x][0]; } }t; struct node{ int l,id,r,v,a,b; }a[N<<1]; inline bool cmpid(node u,node v){ return u.id<v.id; } inline bool cmpb(node u,node v){ return p[u.l]<p[v.l]||(p[u.l]==p[v.l]&&dfn[u.r]<dfn[v.r]); } inline void init(){ read(n),read(m); For(i,1,n)read(col[i]); For(i,1,n){ int x,y; read(x),read(y); if(x>y)swap(x,y); if(x==0)t.dep[rt=y]=1; else add(x,y),add(y,x); } blo=(int)sqrt(n); t.dfs(rt); t.init(); blon++; while(t.top)p[t.st[t.top--]]=blon; For(i,1,m){ read(a[i].l),read(a[i].r); if(dfn[a[i].l]>dfn[a[i].r])swap(a[i].l,a[i].r); read(a[i].a),read(a[i].b);a[i].id=i; } } int vis ,P ; inline void rev(int u){ if(!vis[u]){vis[u]=1,P[col[u]]++;if(P[col[u]]==1)ans++;} else {vis[u]=0,P[col[u]]--;if(P[col[u]]==0)ans--;} } inline void update(int u,int v){ while(u!=v){ if(t.dep[u]>t.dep[v])rev(u),u=t.fa[u][0]; else rev(v),v=t.fa[v][0]; } } inline void solve(){ sort(a+1,a+m+1,cmpb); int lca=t.query(a[1].l,a[1].r); update(a[1].l,a[1].r); rev(lca); a[1].v=ans-(a[1].a!=a[1].b&&P[a[1].a]&&P[a[1].b]); rev(lca); For(i,2,m){ update(a[i-1].l,a[i].l); update(a[i-1].r,a[i].r); lca=t.query(a[i].l,a[i].r); rev(lca); a[i].v=ans-(a[i].a!=a[i].b&&P[a[i].a]&&P[a[i].b]); rev(lca); } sort(a+1,a+m+1,cmpid); For(i,1,m)printf("%d\n",a[i].v); } int main(){ init(); solve(); return 0; }
相关文章推荐
- bzoj3757 苹果树(路径树上莫队)
- BZOJ3757 苹果树
- [bzoj3757]苹果树
- BZOJ-3757 苹果树 LCA 莫队算法 树分块
- 【bzoj3757】 苹果树
- bzoj 3757: 苹果树
- [BZOJ 3757]苹果树
- BZOJ 3757 苹果树 ——莫队算法
- [BZOJ 3757]苹果树:树上莫队
- BZOJ 3757 苹果树 树上莫队
- 【BZOJ-3757】苹果树 块状树 + 树上莫队
- 【BZOJ】【3757】苹果树
- BZOJ 3757 苹果树
- 【树上莫队】bzoj3757 苹果树
- 【bzoj3757】 苹果树
- BZOJ 3757: 苹果树
- 【BZOJ】3757: 苹果树
- bzoj 3757 苹果树(树上莫队算法)
- BZOJ 3757 苹果树 树上莫队
- [BZOJ3757]苹果树(树上莫队+分块)