BZOJ3514:GERALD07加强版(LCT,主席树)
Description
N個點M條邊的無向圖,詢問保留圖中編號在[l,r]的邊的時候圖中的聯通塊個數。
Input
第一行四個整數N、M、K、type,代表點數、邊數、詢問數以及詢問是否加密。
接下來M行,代表圖中的每條邊。
接下來K行,每行兩個整數L、R代表一組詢問。對于type=0的測試點,讀入的L和R即為詢問的L、R;對于type=1的測試點,每組詢問的L、R應為L xor lastans和R xor lastans。
Output
?K行每行一個整數代表該組詢問的聯通塊個數。
Sample Input
3 5 4 01 3
1 2
2 1
3 2
2 2
2 3
1 5
5 5
1 2
Sample Output
21
3
1
HINT
對于100%的數據,1≤N、M、K≤200,000。
Solution
$namespace$真是個好東西QAQ
每次往里加邊,如果構成環的話就把最早的那條邊刪掉,這個可以用$LCT$隨便做。
定義一個數組$Early[i]$,表示加第$i$條邊的時候,會把哪條邊刪掉。
特殊的,如果不刪邊,$Early[i]=0$。如果第$i$條邊是自環,$Early[i]=i$。
然后對$Early$數組建主席樹,每次詢問的答案就是$[l,r]$區間內小于等于$l-1$的數個個數。
正確性……如果一條邊$i$的$Early[i]$在$l$后面的話,那么加入$i$的時候,因為會產生環所以不會對連通塊情況產生影響。否則如果$Early[i]$在$l$的前面的話,加入$i$就會對連通塊情況產生影響……
大體就是這樣子具體我也不會
Code
1 #include<iostream> 2 #include<cstdio> 3 #define N (400009) 4 using namespace std; 5 6 int n,m,k,opt,Early[N],x[N],y[N]; 7 8 namespace LCT 9 { 10 int Father[N],Son[N][2],Val[N],Min[N],Rev[N]; 11 12 int Get(int x) 13 { 14 return Son[Father[x]][1]==x; 15 } 16 int Is_root(int x) 17 { 18 return Son[Father[x]][0]!=x && Son[Father[x]][1]!=x; 19 } 20 void Pushup(int x) 21 { 22 Min[x]=x; 23 int ls=Son[x][0],rs=Son[x][1]; 24 if (Val[Min[ls]]<Val[Min[x]]) Min[x]=Min[ls]; 25 if (Val[Min[rs]]<Val[Min[x]]) Min[x]=Min[rs]; 26 } 27 void Pushdown(int x) 28 { 29 if (Rev[x]) 30 { 31 Rev[Son[x][0]]^=1; 32 Rev[Son[x][1]]^=1; 33 swap(Son[x][0],Son[x][1]); 34 Rev[x]=0; 35 } 36 } 37 void Rotate(int x) 38 { 39 int wh=Get(x); 40 int fa=Father[x],fafa=Father[fa]; 41 if (!Is_root(fa)) Son[fafa][Son[fafa][1]==fa]=x; 42 Father[fa]=x; Son[fa][wh]=Son[x][wh^1]; 43 if (Son[fa][wh]) Father[Son[fa][wh]]=fa; 44 Father[x]=fafa; Son[x][wh^1]=fa; 45 Pushup(fa); Pushup(x); 46 } 47 void Push(int x) 48 { 49 if (!Is_root(x)) Push(Father[x]); 50 Pushdown(x); 51 } 52 void Splay(int x) 53 { 54 Push(x); 55 for (int fa; !Is_root(x); Rotate(x)) 56 if (!Is_root(fa=Father[x])) 57 Rotate(Get(fa)==Get(x)?fa:x); 58 } 59 void Access(int x) 60 { 61 for (int y=0; x; y=x,x=Father[x]) 62 Splay(x), Son[x][1]=y, Pushup(x); 63 } 64 void Make_root(int x) 65 { 66 Access(x); Splay(x); Rev[x]^=1; 67 } 68 int Find_root(int x) 69 { 70 Access(x); Splay(x); 71 while (Son[x][0]) x=Son[x][0]; 72 return x; 73 } 74 void Link(int x,int y) 75 { 76 Make_root(x); Father[x]=y; 77 } 78 void Cut(int x,int y) 79 { 80 Make_root(x); Access(y); Splay(y); 81 Son[y][0]=Father[x]=0; Pushup(y); 82 } 83 int Query(int x,int y) 84 { 85 Make_root(x); Access(y); Splay(y); 86 return Min[y]; 87 } 88 void Build_Early() 89 { 90 for (int i=1; i<=m; ++i) Val[n+i]=i; 91 for (int i=0; i<=n; ++i) Val[i]=2e8,Min[i]=i; 92 for (int i=1; i<=m; ++i) 93 { 94 scanf("%d%d",&x[i],&y[i]); 95 if (x[i]==y[i]) {Early[i]=i; continue;} 96 if (Find_root(x[i])!=Find_root(y[i])) 97 Link(x[i],i+n), Link(y[i],i+n); 98 else 99 { 100 int p=Query(x[i],y[i]); 101 Early[i]=p-n; 102 Cut(x[p-n],p); Cut(y[p-n],p); 103 Link(x[i],i+n); Link(y[i],i+n); 104 } 105 } 106 } 107 } 108 109 namespace Sgt 110 { 111 struct Sgt{int ls,rs,val;}Segt[N*40]; 112 int sgt_num,Root[N]; 113 114 int Update(int pre,int l,int r,int x) 115 { 116 int now=++sgt_num; 117 Segt[now]=Segt[pre]; 118 Segt[now].val++; 119 if (l==r) return now; 120 int mid=(l+r)>>1; 121 if (x<=mid) Segt[now].ls=Update(Segt[now].ls,l,mid,x); 122 else Segt[now].rs=Update(Segt[now].rs,mid+1,r,x); 123 return now; 124 } 125 int Query(int u,int v,int l,int r,int l1,int r1) 126 { 127 if (l>r1 || r<l1) return 0; 128 if (l1<=l && r<=r1) return Segt[v].val-Segt[u].val; 129 int mid=(l+r)>>1; 130 return Query(Segt[u].ls,Segt[v].ls,l,mid,l1,r1)+Query(Segt[u].rs,Segt[v].rs,mid+1,r,l1,r1); 131 } 132 void Solve() 133 { 134 for (int i=1; i<=m; ++i) 135 Root[i]=Update(Root[i-1],0,2e5,Early[i]); 136 int ans=0,l,r; 137 for (int i=1; i<=k; ++i) 138 { 139 scanf("%d%d",&l,&r); 140 if (opt) l^=ans, r^=ans; 141 ans=n-Query(Root[l-1],Root[r],0,2e5,0,l-1); 142 printf("%d\n",ans); 143 } 144 } 145 } 146 147 int main() 148 { 149 scanf("%d%d%d%d",&n,&m,&k,&opt); 150 LCT::Build_Early(); 151 Sgt::Solve(); 152 }轉載于:https://www.cnblogs.com/refun/p/10088908.html
總結
以上是生活随笔為你收集整理的BZOJ3514:GERALD07加强版(LCT,主席树)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 查看应用监听的端口
- 下一篇: windows 安装与使用redis