[codeforces117E]Tree or not Tree
来源:互联网 发布:unity3d小球滚动 编辑:程序博客网 时间:2024/06/06 01:11
题目大意
给定一个n个点的环套树,每条边有开、关两个状态。接下来m次操作,每次给定一对数(x,y),对于x到y的最短路径(如果有多条就选择经过点字典序的一条),路径上经过所有边的状态取反(开变关,关变开)。每次操作后输出只考虑开状态的边时,有多少个联通块。
n,m≤100000
分析
考虑在树上怎么做。
最短路径只有一条,那么直接可以确定。
对于当前的树,它的联通块个数就是n-状态为开的边的个数(连接一条边相当于合并两个联通块)。
现在变成了环套树,如果连接一条边,两个端点是来自不同联通块的,那么答案也是-1,否则答案不变。
由于只有一个环,当环上所有边都被选时才会出现答案不变的情况。那么当结论改成(答案为n-状态为开的边的个数+[环上的边都被选])是一样的。
由于是环套树,最短路径最多只有两条,判断的只是走到环上时,第一个不同的点而已。这个很好判断。
剩下的就是修改边的状态了,树链剖分解决!
注意x=y的情况。
时间复杂度
我的代码很长很丑
#include <cstdio>#include <cstring>#include <algorithm>using namespace std;const int N=100005,M=200005,T=262222,Log=17;typedef long long LL;int n,m,h[N],e[M],nxt[M],ans,tot,s,H[N],E[M],Nxt[M],a[N],b[N],size[N],dfn[N],seq[N],top[N],r,sum[T],id[N];int t1[T],t2[T],tag1[T],tag2[T],fa[N][Log],dep[N];bool v[N];char c;int read(){ for (c=getchar();c<'0' || c>'9';c=getchar()); int x=c-48; for (c=getchar();c>='0' && c<='9';c=getchar()) x=x*10+c-48; return x;}void add(int x,int y){ e[++tot]=y; nxt[tot]=h[x]; h[x]=tot;}void Add(int x,int y){ E[++tot]=y; Nxt[tot]=H[x]; H[x]=tot;}bool init(int x,int y){ v[x]=1; b[++tot]=x; for (int i=h[x];i;i=nxt[i]) if (e[i]!=y) { if (!v[e[i]]) { if (init(e[i],x)) return 1; }else { for (int j=tot;b[j]!=e[i];j--) a[++s]=b[j]; a[++s]=e[i]; return 1; } } tot--; v[x]=0; return 0;}void build(int x,int ID){ v[x]=1; dep[x]=dep[fa[x][0]]+1; id[x]=ID; for (int i=h[x];i;i=nxt[i]) if (!v[e[i]]) { Add(x,e[i]); fa[e[i]][0]=x; build(e[i],ID); size[x]=size[e[i]]+1; }}void ins(int l,int r,int v,int x){ sum[x]++; if (l==r) return; int mid=l+r>>1; if (v<=mid) ins(l,mid,v,x<<1);else ins(mid+1,r,v,x<<1|1);}void dfs(int x,int y){ dfn[x]=++tot; seq[tot]=x; top[tot]=r; ins(1,n,tot,1); int i,j=0; for (i=H[x];i;i=Nxt[i]) if (E[i]!=y && (!j || size[E[i]]>size[j])) j=E[i]; if (!j) return; dfs(j,x); for (i=H[x];i;i=Nxt[i]) if (E[i]!=y && E[i]!=j) { r=tot+1; dfs(E[i],x); }}void change1(int l,int r,int a,int b,int x){ if (l==a && r==b) { t1[x]=sum[x]-t1[x]; tag1[x]^=1; return; } int mid=l+r>>1; if (tag1[x]) { tag1[x]=0; tag1[x<<1]^=1; t1[x<<1]=sum[x<<1]-t1[x<<1]; tag1[x<<1|1]^=1; t1[x<<1|1]=sum[x<<1|1]-t1[x<<1|1]; } if (b<=mid) change1(l,mid,a,b,x<<1); else if (a>mid) change1(mid+1,r,a,b,x<<1|1); else { change1(l,mid,a,mid,x<<1); change1(mid+1,r,mid+1,b,x<<1|1); } t1[x]=t1[x<<1]+t1[x<<1|1];}void change2(int l,int r,int a,int b,int x){ if (l==a && r==b) { t2[x]=r-l+1-t2[x]; tag2[x]^=1; return; } int mid=l+r>>1; if (tag2[x]) { tag2[x]=0; tag2[x<<1]^=1; t2[x<<1]=mid-l+1-t2[x<<1]; tag2[x<<1|1]^=1; t2[x<<1|1]=r-mid-t2[x<<1|1]; } if (b<=mid) change2(l,mid,a,b,x<<1); else if (a>mid) change2(mid+1,r,a,b,x<<1|1); else { change2(l,mid,a,mid,x<<1); change2(mid+1,r,mid+1,b,x<<1|1); } t2[x]=t2[x<<1]+t2[x<<1|1];}int getlca(int x,int y){ if (dep[x]<dep[y]) x^=y^=x^=y; for (int i=Log-1;i>=0;i--) if (dep[fa[x][i]]>=dep[y]) x=fa[x][i]; for (int i=Log-1;i>=0;i--) if (fa[x][i]!=fa[y][i]) { x=fa[x][i]; y=fa[y][i]; } if (x!=y) x=fa[x][0]; return x;}void go(int x,int y){ if (x==y) return; x=dfn[x]; int k=top[x]; if (k<=dfn[y]) k=dfn[y]+1; change1(1,n,k,x,1); go(fa[seq[k]][0],y);}int main(){ n=read(); m=read(); for (int i=0;i<n;i++) { int x=read(),y=read(); add(x,y); add(y,x); } tot=0; init(1,0); memset(v,0,sizeof(v)); for (int i=1;i<=s;i++) v[a[i]]=1; tot=0; n++; dep[n]=1; for (int i=1;i<=s;i++) { id[a[i]]=i; for (int j=h[a[i]];j;j=nxt[j]) if (!v[e[j]]) { Add(n,e[j]); fa[e[j]][0]=n; build(e[j],i); } } r=1; tot=0; dfs(n,0); for (int j=1;j<Log;j++) { for (int i=1;i<=n;i++) fa[i][j]=fa[fa[i][j-1]][j-1]; } ans=n-1; while (m--) { int x=read(),y=read(),lca; if (x==y) { printf("%d\n",ans); continue; } if (a[id[x]]!=x && a[id[y]]!=y) lca=getlca(x,y);else lca=n; if (a[id[x]]!=x) go(x,lca); if (a[id[y]]!=y) go(y,lca); if (lca==n) { int p=id[x],q=id[y],pre=(p>1)?p-1:s,nxt=(p<s)?p+1:1; if (p<q) { if (q-p<s/2.0 || q-p==s/2.0 && a[nxt]<a[pre]) change2(1,s,p,q-1,1); else { if (p>1) change2(1,s,1,p-1,1); change2(1,s,q,s,1); } }else if (p>q) { if (p-q<s/2.0 || p-q==s/2.0 && a[nxt]>a[pre]) change2(1,s,q,p-1,1); else { change2(1,s,p,s,1); if (q>1) change2(1,s,1,q-1,1); } } } ans=n-t1[1]-t2[1]-1; if (t2[1]==s) ans++; printf("%d\n",ans); } return 0;}
0 0
- [codeforces117E]Tree or not Tree
- check a tree is balanced or not
- Tree or Tree
- hash tree or Merkle tree
- Check if the given binary tree is BST or not.
- Binary Indexed Tree(BIT) OR Fenwick Tree
- 判断是否为完全二叉树 Check whether a binary tree is a complete tree or not
- A program to check if a binary tree is BST or not
- <iOS> The operation could not be performed because of one or more tree conflicts.
- Tree
- tree
- tree
- TREE
- Tree
- Tree
- tree
- tree
- tree
- 重定向和转发的区别
- 栈的简单实现
- jsp标准标签库
- Java基础学习(五)
- 容斥原理 && 欧拉函数 && 抽屉原理
- [codeforces117E]Tree or not Tree
- 搭建一个spring-boot项目 4
- hduoj-2824【欧拉函数】
- List.addAll()操作总结
- CodeForces
- [jzoj4665][CF407E]k-d-sequence
- 个人对this总结
- bzoj1634
- 云计算与数据中心