【bzoj3514】 Codechef MARCH14 GERALD07加强版
http://www.lydsy.com/JudgeOnline/problem.php?id=3514?(題目鏈接)
題意
給出$n$個點$m$條邊的無向圖,詢問保留圖中編號在$[l,r]$的邊的時候圖中的連通塊的個數(shù)。
Solution
將邊的編號作為權(quán)值用LCT維護一個最大生成樹,同時記錄一下加入當(dāng)前邊$i$會把哪一條原本在生成樹中的邊踢掉,記作$ntr[i]$。如果不會踢掉任意一條邊,那么$ntr[i]=0$。如果$i$是自環(huán),那么$ntr[i]=i$。
求出$ntr$數(shù)組有什么用呢,我們以它構(gòu)建一棵主席樹。對于一個詢問$[l,r]$,我們想知道在這些邊中有用的邊有幾條,那么有用的邊$ntr$的前一條邊的編號一定是在$l$之前的,所以我們在主席樹上查詢一下區(qū)間$[l,r]$中$ntr$在$[0,l-1]$中的邊有幾條。這樣查出來的值就是有用的邊的條數(shù),每加入一條有用的邊,都會時連通塊個數(shù)-1,于是我們就可以統(tǒng)計答案了。
細節(jié)
cut的時候cut的是被ntr的邊兩端的節(jié)點,手一快就打錯了,還查了好久T_T
代碼
// bzoj3514 #include<algorithm> #include<iostream> #include<cstdlib> #include<cstring> #include<cstdio> #include<cmath> #define LL long long #define lim 1000000000 #define inf 2147483640 #define Pi acos(-1.0) #define free(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout) using namespace std;const int maxn=200010; int n,m,Q,T,ans,rt[maxn],ntr[maxn]; struct edge {int u,v;}e[maxn]; struct node {int son[2],s,rev;int& operator [] (int x) {return son[x];} };namespace LCT {int fa[maxn<<1];node tr[maxn<<1];void reverse(int x) {tr[x].rev^=1;swap(tr[x][0],tr[x][1]);}void pushup(int x) {tr[x].s=x<=n ? inf : x;int l=tr[x][0],r=tr[x][1];if (l) tr[x].s=min(tr[x].s,tr[l].s);if (r) tr[x].s=min(tr[x].s,tr[r].s);}void pushdown(int x) {if (tr[fa[x]][0]==x || tr[fa[x]][1]==x) pushdown(fa[x]);if (tr[x].rev) {if (tr[x][0]) reverse(tr[x][0]);if (tr[x][1]) reverse(tr[x][1]);tr[x].rev^=1;}}void rotate(int x) {int y=fa[x],z=fa[y],l,r;l=tr[y][1]==x;r=l^1;if (tr[z][0]==y || tr[z][1]==y) tr[z][tr[z][1]==y]=x;fa[x]=z;fa[y]=x;fa[tr[x][r]]=y;tr[y][l]=tr[x][r];tr[x][r]=y;pushup(y);pushup(x);}void splay(int x) {pushdown(x);while (tr[fa[x]][0]==x || tr[fa[x]][1]==x) {int y=fa[x],z=fa[y];if (tr[z][0]==y || tr[z][1]==y) {if (tr[z][0]==y ^ tr[y][0]==x) rotate(x);else rotate(y);}rotate(x);}}void access(int x) {for (int y=0;x;y=x,x=fa[x])splay(x),tr[x][1]=y,pushup(x);}void makeroot(int x) {access(x);splay(x);reverse(x);}int query(int x,int y) {makeroot(x);access(y);splay(y);return tr[y].s;}void link(int x,int y) {makeroot(x);fa[x]=y;}void cut(int x,int y) {makeroot(x);access(y);splay(y);fa[x]=tr[y][0]=0;pushup(y);}int find(int x) {return fa[x] ? find(fa[x]) : x;}void main() {for (int i=1;i<=m;i++) {scanf("%d%d",&e[i].u,&e[i].v);if (e[i].u==e[i].v) ntr[i]=i;else if (find(e[i].u)==find(e[i].v)) {int x=query(e[i].u,e[i].v);ntr[i]=x-n;cut(x,e[x-n].u);cut(x,e[x-n].v);link(i+n,e[i].u);link(i+n,e[i].v);}else ntr[i]=0,link(i+n,e[i].u),link(i+n,e[i].v);}} }namespace Chairtree {int sz;node tr[maxn*40];void build(int &u,int v,int l,int r,int val) {if (!u) u=++sz;if (l==r) {tr[u].s=tr[v].s+1;return;}int mid=(l+r)>>1;if (val<=mid) build(tr[u][0],tr[v][0],l,mid,val),tr[u][1]=tr[v][1];else build(tr[u][1],tr[v][1],mid+1,r,val),tr[u][0]=tr[v][0];tr[u].s=tr[tr[u][0]].s+tr[tr[u][1]].s;}int query(int u,int v,int l,int r,int ql,int qr) {if (!u && !v) return 0;if (l==ql && r==qr) return tr[v].s-tr[u].s;int mid=(l+r)>>1;if (qr<=mid) return query(tr[u][0],tr[v][0],l,mid,ql,qr);else if (ql>mid) return query(tr[u][1],tr[v][1],mid+1,r,ql,qr);else return query(tr[u][0],tr[v][0],l,mid,ql,mid)+query(tr[u][1],tr[v][1],mid+1,r,mid+1,qr);} } using namespace Chairtree;int main() {scanf("%d%d%d%d",&n,&m,&Q,&T);LCT::main();for (int i=1;i<=m;i++) build(rt[i],rt[i-1],0,m,ntr[i]);for (int l,r,i=1;i<=Q;i++) {scanf("%d%d",&l,&r);if (T) l^=ans,r^=ans;ans=n-query(rt[l-1],rt[r],0,m,0,l-1);printf("%d\n",ans);}return 0; }?
轉(zhuǎn)載于:https://www.cnblogs.com/MashiroSky/p/6484381.html
總結(jié)
以上是生活随笔為你收集整理的【bzoj3514】 Codechef MARCH14 GERALD07加强版的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Windows Server 2003
- 下一篇: 基于分布式光纤传感的全厂数字在线监测设计