1. 程式人生 > 實用技巧 >洛谷P2542 [AHOI2005] 航線規劃(樹鏈剖分+離線樹轉圖+思維)

洛谷P2542 [AHOI2005] 航線規劃(樹鏈剖分+離線樹轉圖+思維)

感謝博主:https://www.luogu.com.cn/blog/116113X/solution-p2542

題意:略:

解法:

#include<bits/stdc++.h>
#define ll long long
#define rep(i,a,n) for(int i=a;i<=n;i++)
#define per(i,n,a) for(int i=n;i>=a;i--)
#define endl '\n'
#define eps 0.000000001
#define pb push_back
#define mem(a,b) memset(a,b,sizeof(a))
#define
IO ios::sync_with_stdio(false);cin.tie(0); using namespace std; const int INF=0x3f3f3f3f; const ll inf=0x3f3f3f3f3f3f3f3f; const int mod=1e9+7; const int maxn=1e5+5; int tot,head[maxn]; struct E{ int to,next; }edge[maxn<<1]; void add(int u,int v){ edge[tot].to=v; edge[tot].next=head[u]; head[u]
=tot++; } struct nod{ int t,a,b; }dt[maxn]; int n,m,fa[maxn]; int find(int x){ while(x!=fa[x]) x=fa[x]=fa[fa[x]]; return x; } int uu[maxn],vv[maxn],vis[maxn]; map<pair<int,int>,int>mp; int v[maxn],root; int dep[maxn],siz[maxn],son[maxn]; void dfs1(int u,int f){ fa[u]=f; dep[u]
=dep[f]+1; siz[u]=1; int maxsize=-1; for(int i=head[u];i!=-1;i=edge[i].next){ int v=edge[i].to; if(v==f) continue; dfs1(v,u); siz[u]+=siz[v]; if(siz[v]>maxsize){ maxsize=siz[v]; son[u]=v; } } } int tim,dfn[maxn],top[maxn],w[maxn]; void dfs2(int u,int t){ dfn[u]=++tim; top[u]=t; if(!son[u]) return ; dfs2(son[u],t); for(int i=head[u];i!=-1;i=edge[i].next){ int v=edge[i].to; if(v==fa[u]||v==son[u]) continue; dfs2(v,v); } } struct node{ int l,r,sum,lz; }tree[maxn<<2]; inline void build(int i,int l,int r){ tree[i].l=l;tree[i].r=r,tree[i].lz=-1; if(l==r){ tree[i].sum=1; return ; } ll mid=(l+r)>>1; build(2*i,l,mid); build(2*i+1,mid+1,r); tree[i].sum=tree[2*i].sum+tree[i*2+1].sum; } inline void push_down(int i){ if(tree[i].lz!=-1){ tree[i*2].lz=tree[i].lz; tree[i*2+1].lz=tree[i].lz; ll mid=(tree[i].l+tree[i].r)/2; tree[i*2].sum=tree[i].lz*(mid-tree[i*2].l+1); tree[i*2+1].sum=tree[i].lz*(tree[i*2+1].r-mid); tree[i].lz=-1; } return ; } inline void modify(int i,int l,int r,int k){ if(tree[i].r<=r && tree[i].l>=l){ tree[i].sum=k*(tree[i].r-tree[i].l+1); tree[i].lz=k; return ; } push_down(i); if(tree[i*2].r>=l) modify(i*2,l,r,k); if(tree[i*2+1].l<=r) modify(i*2+1,l,r,k); tree[i].sum=tree[i*2].sum+tree[i*2+1].sum; } inline int query(int i,int l,int r){ if(tree[i].l>=l && tree[i].r<=r) return tree[i].sum; if(tree[i].r<l || tree[i].l>r) return 0; push_down(i); ll s=0; if(tree[i*2].r>=l) s+=query(i*2,l,r); if(tree[i*2+1].l<=r) s+=query(i*2+1,l,r); return s; } void mchain(int x,int y,int z){ while(top[x]!=top[y]){ if(dep[top[x]]<dep[top[y]]) std::swap(x,y); modify(1,dfn[top[x]],dfn[x],z); x=fa[top[x]]; } if(dep[x]>dep[y]) std::swap(x,y); modify(1,dfn[x]+1,dfn[y],z); } int qchain(int x,int y){ int ret=0; while(top[x]!=top[y]){ if(dep[top[x]]<dep[top[y]]) std::swap(x,y); ret+=query(1,dfn[top[x]],dfn[x]); x=fa[top[x]]; } if(dep[x]>dep[y]) std::swap(x,y); ret+=query(1,dfn[x]+1,dfn[y]); return ret; } int main(){ scanf("%d%d",&n,&m);mem(head,-1); rep(i,1,m){ scanf("%d%d",&uu[i],&vv[i]); } int cnt=0; while(1){ int op;scanf("%d",&op); if(op==-1) break; int a,b;scanf("%d%d",&a,&b); dt[++cnt]={op,a,b}; if(!op) mp[{a,b}]=mp[{b,a}]=1; } rep(i,1,n) fa[i]=i; rep(i,1,m){ int u=find(uu[i]),v=find(vv[i]); if(!mp[{uu[i],vv[i]}]&&fa[u]!=v){ fa[u]=v; add(uu[i],vv[i]); add(vv[i],uu[i]); vis[i]=true; } } mem(fa,0); dfs1(1,-1); dfs2(1,1); build(1,1,n); rep(i,1,m){ if(!vis[i]&&!mp[{uu[i],vv[i]}]){ int a=uu[i],b=vv[i]; mchain(a,b,0); } } stack<int> q; for(int i=cnt;i>=1;i--){ int ans=0,t=dt[i].t,a=dt[i].a,b=dt[i].b; if(t){ ans=qchain(a,b); q.push(ans); }else{ mchain(a,b,0); } } while(!q.empty()){ int now=q.top(); cout<<now<<endl; q.pop(); } }
View Code