标签:memset 重复 void 这不 main case 需要 math 必须
//Serene #include<algorithm> #include<iostream> #include<cstring> #include<cstdlib> #include<cstdio> #include<cmath> #include<vector> using namespace std; const int maxn=1e5+10; int T,n,m,Q; int aa,ff;char cc; int read() { aa=0;cc=getchar();ff=1; while(cc<‘0‘||cc>‘9‘) { if(cc==‘-‘) ff=-1; cc=getchar(); } while(cc>=‘0‘&&cc<=‘9‘) aa=aa*10+cc-‘0‘,cc=getchar(); return aa*ff; } struct Edge{ int u,v; }; vector<Edge> G; int fir[maxn],nxt[2*maxn],to[2*maxn],e=0; void add(int x,int y) { to[++e]=y;nxt[e]=fir[x];fir[x]=e; to[++e]=x;nxt[e]=fir[y];fir[y]=e; } int f[maxn]; int find(int x) {return x==f[x]? x:f[x]=find(f[x]);} int fa[maxn],size[maxn],son[maxn],dep[maxn]; void dfs1(int pos) { size[pos]=1;int y,z; for(y=fir[pos];y;y=nxt[y]) { if((z=to[y])==fa[pos]) continue; fa[z]=pos;dep[z]=dep[pos]+1; dfs1(z); size[pos]+=size[z]; if(size[z]>size[son[pos]]) son[pos]=z; } } int id[maxn],top[maxn],cnt; void dfs2(int pos,int tp) { id[pos]=++cnt; top[pos]=tp; if(!son[pos]) return; dfs2(son[pos],tp); int y,z; for(y=fir[pos];y;y=nxt[y]) { if((z=to[y])==fa[pos]||to[y]==son[pos]) continue; dfs2(z,z); } } int sz[maxn]; int q(int l,int r) { int rs=0;l--; while(r) { rs+=sz[r]; r-=(r&-r); } while(l) { rs-=sz[l]; l-=(l&-l); } return rs; } void chge(int l,int r){ int rr; for(r=find(r);r>=l;r=f[r]) { rr=r; while(rr<=n){ sz[rr]--; rr+=(rr&-rr); } f[r]=find(r-1); } } void get_lca(int x,int y,int p) { int rs=0; while(top[x]!=top[y]) { if(dep[top[x]]<dep[top[y]]) swap(x,y); if(p) rs+=q(id[top[x]],id[x]); else chge(id[top[x]],id[x]); x=fa[top[x]]; } if(x!=y) { if(dep[x]<dep[y]) swap(x,y); if(p) rs+=q(id[y]+1,id[x]); else chge(id[y]+1,id[x]); } if(p) printf("%d\n",rs); } int main() { T=read(); int x,y,z,xx,yy; for(int qaq=1;qaq<=T;++qaq) { n=read();m=read(); G.clear(); e=0; cnt=0; memset(fir,0,sizeof(fir)); memset(son,0,sizeof(son)); memset(fa,0,sizeof(fa)); for(int i=1;i<=n;++i) f[i]=i; for(int i=1;i<=m;++i) { x=read();y=read(); xx=find(x);yy=find(y); if(xx!=yy) add(x,y),f[xx]=yy; else G.push_back(Edge{x,y}); } Q=read(); dep[1]=1; dfs1(1); dfs2(1,1); for(int i=1;i<=n;++i) f[i]=i; for(int i=1;i<=n;++i) sz[i]=(i&-i); z=G.size(); for(int i=0;i<z;++i) get_lca(G[i].u,G[i].v,0); printf("Case #%d:\n",qaq); for(int i=1;i<=Q;++i) { x=read();y=read();z=read(); get_lca(y,z,x-1); } } return 0; }
除此之外,也可以用树状数组维护每个点到根的距离,然后每次修改就是把子树的区间-1,这样就是区间修改单点查询了。
不过还是要用并查集维护每条边上方第一个没有清零的边(有用的边)。
所以说这道题的重点就是避免重复的修改浪费时间,用并查集维护上方第一个没有清零的边。
HDU6200 mustedge mustedge mustedge
标签:memset 重复 void 这不 main case 需要 math 必须
原文地址:http://www.cnblogs.com/Serene-shixinyi/p/7646803.html