HDU 6203 ping ping ping (在线倍增lca+DFS序+树状数组)
生活随笔
收集整理的這篇文章主要介紹了
HDU 6203 ping ping ping (在线倍增lca+DFS序+树状数组)
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
題目鏈接:http://acm.hdu.edu.cn/showproblem.php?pid=6203
#include<bits/stdc++.h> using namespace std;#define debug puts("YES"); #define rep(x,y,z) for(int (x)=(y);(x)<(z);(x)++) #define ll unsigned long long#define lrt int l,int r,int rt #define lson l,mid,rt<<1 #define rson mid+1,r,rt<<1|1 #define root l,r,rt #define mst(a,b) memset((a),(b),sizeof(a)) const int maxn =1e4+5; const int mod=9999991; const int ub=1e6; ll powmod(ll x,ll y){ll t; for(t=1;y;y>>=1,x=x*x%mod) if(y&1) t=t*x%mod; return t;} ll gcd(ll x,ll y){return y?gcd(y,x%y):x;} /* 題目大意:有棵樹, 有些節(jié)點(diǎn)的服務(wù)器壞掉了, 現(xiàn)在要找到這些壞服務(wù)器, 有一些數(shù)據(jù),每一個(gè)節(jié)點(diǎn)對表面, u到v的路徑不通,問這樣下來最后至少有多少個(gè)服務(wù)器。分析一下其實(shí)思路還是很清楚的, 對一個(gè)特定的點(diǎn)對,要想貢獻(xiàn)最多的破壞對數(shù), 肯定是lca,那么我們先對于所有的點(diǎn)對按其lca深度從大到小排序, 這樣就可以保證無后效性,然后判斷當(dāng)前點(diǎn)對, 如果其中存在已經(jīng)被刪除的點(diǎn),那該點(diǎn)對無貢獻(xiàn), 否則,累計(jì)答案,并把其lca子樹刪去。關(guān)于子樹刪除的操作可以用dfs序加上樹狀數(shù)組維護(hù),關(guān)于lca 可以用動態(tài)倍增算法搞一下,剛開始寫的樹剖被t了,可能是樹剖對于單純只要個(gè)lca的 問題時(shí)間復(fù)雜度不太給力。這道題就是一套組合拳,思路并不難。時(shí)間復(fù)雜度:O(nlogn),注意內(nèi)存大小等等。 */ int n,u,v,p,ans=0; ///鏈?zhǔn)角跋蛐?struct node{int u,nxt; }e[maxn<<1]; int head[maxn],tot=0,id=0; void add(int x,int y) {e[tot]=node{y,head[x]};head[x]=tot++; } /* ///樹鏈剖分求LCA int dep[maxn],siz[maxn],son[maxn],fa[maxn]; void init() {mst(head,-1),mst(son,0);tot=dep[1]=id=0; } void dfs1(int u) {siz[u]=1;for(int i=head[u];~i;i=e[i].nxt){int v=e[i].u;if(v!=fa[u]){dep[v]=dep[u]+1;fa[v]=u;dfs1(v);siz[u]+=siz[v];if(siz[son[u]]<siz[v]) son[u]=v;}} } int top[maxn],idx[maxn]; void dfs2(int u,int tp) {top[u]=tp;idx[u]=++id;if(son[u]) dfs2(son[u],tp);for(int i=head[u];~i;i=e[i].nxt){int v=e[i].u;if(v==fa[u]||v==son[u]) continue;dfs2(v,v);} } int lca(int u,int v) {int tpu=top[u],tpv=top[v];while(tpu!=tpv){if(dep[tpu]<dep[tpv]){swap(u,v);swap(tpu,tpv);}u=fa[tpu];tpu=top[u];}return dep[u]>dep[v]?v:u; } */ ///DFS序和樹狀數(shù)組維護(hù) int bit[maxn<<1]; int lowbit(int x) {return x&(-x); } void Add(int x,int d) {for(;x<maxn;bit[x]+=d,x+=lowbit(x)); } int sum(int x) {int ret=0;for(;x>0;ret+=bit[x],x-=lowbit(x));return ret; } int pl[maxn],pr[maxn];///DFS序維護(hù) int pa[maxn][20],dep[maxn];///在線倍增lca void init() {mst(head,-1),mst(pa,0);tot=id=dep[1]=0; } void dfs(int u,int pre) {if(pre!=-1) dep[u]=dep[pre]+1;pl[u]=++id;pa[u][0]=pre;for(int i=1;i<20;i++) pa[u][i]=pa[pa[u][i-1]][i-1];///初始化for(int i=head[u];~i;i=e[i].nxt){int v=e[i].u;if(v==pre) continue;dfs(v,u);}pr[u]=id; } int lca(int u,int v) {int i,j;if(dep[u]<dep[v]) swap(u,v);///以u為深度大的那個(gè)for(i=0;(1<<i)<=dep[u];i++);i--;for(j=i;j>=0;j--) if(dep[u]-(1<<j)>=dep[v])u=pa[u][j];if(u==v) return u;for(j=i;j>=0;j--) if(pa[u][j]&&pa[u][j]!=pa[v][j])u=pa[u][j],v=pa[v][j];return pa[u][0]; } ///詢問點(diǎn) struct qy {int u,v,f;bool operator<(const qy& y) const{return dep[f]>dep[y.f];} }q[maxn*5];int main() {while(scanf("%d",&n)!=EOF){init();///初始化前向星for(int i=0;i<n;i++){scanf("%d%d",&u,&v);u++,v++;add(u,v),add(v,u);}///dfs1(1),dfs2(1,1);ans=id=0,mst(bit,0),dfs(1,0);///樹狀數(shù)組維護(hù)DSF序scanf("%d",&p);for(int i=0;i<p;i++){scanf("%d%d",&q[i].u,&q[i].v);q[i].u++,q[i].v++;q[i].f=lca(q[i].u,q[i].v);///cout<<q[i].u<<" "<<q[i].v<<" "<<q[i].f<<endl;}sort(q,q+p);for(int i=0;i<p;i++){int f=q[i].f;if(sum(pl[q[i].u])||sum(pl[q[i].v]));else{ans++;Add(pl[f],1),Add(pr[f]+1,-1);}}printf("%d\n",ans);}return 0; }?
總結(jié)
以上是生活随笔為你收集整理的HDU 6203 ping ping ping (在线倍增lca+DFS序+树状数组)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: K8S中Busybox容器安装软件
- 下一篇: 卸载360超级root