一般图匹配带花树
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 #include <bits/stdc++.h> 2 3 using namespace std; 4 const int maxm=50100; 5 const int maxn=500; 6 char ch[200]; 7 int t,to[maxm],head[maxn],nex[maxm],tot; 8 9 10 11 struct Blossom { 12 int p[maxn], vi[maxn], tag, fl[maxn], c[maxn], pr[maxn], q[maxn], r; 13 int find(int x) { 14 return x == p[x] ? x : p[x] = find(p[x]); 15 } 16 void add(int u, int v) { 17 t++; 18 to[t] = v; 19 nex[t] = head[u]; 20 head[u] = t; 21 } 22 int lca(int u, int v) { 23 ++tag; 24 u = find(u); 25 v = find(v); 26 for (;; swap(u, v)) 27 if (u) { 28 if (fl[u] == tag) return u; 29 fl[u] = tag; 30 u = find(pr[c[u]]); 31 } 32 } 33 void blo(int u, int v, int l) { 34 for (; find(u) != l; v = c[u], u = pr[v]) { 35 pr[u] = v; 36 if (vi[c[u]] == 1) 37 vi[q[++r] = c[u]] = 0; 38 if (find(u) == u) p[u] = l; 39 if (find(c[u]) == c[u]) p[c[u]] = l; 40 } 41 42 } 43 bool aug(int s) { 44 for (int i = 1; i <= tot; i++) { 45 p[i] = i; 46 vi[i] = -1; 47 } 48 vi[q[r = 1] = s] = 0; 49 int x, y; 50 for (int i = 1; i <= r; i++) 51 for (int j = head[x = q[i]]; j; j = nex[j]) 52 if (vi[y = to[j]] == -1) { 53 pr[y] = x; 54 vi[y] = 1; 55 if (!c[y]) { 56 for (int u = x, v = y, t; u; v = t, u = pr[v]) { 57 t = c[u]; 58 c[u] = v; 59 c[v] = u; 60 } 61 return 1; 62 } 63 vi[q[++r] = c[y]] = 0; 64 } else if (!vi[y] && find(x) != find(y)) { 65 int l = lca(x, y); 66 blo(x, y, l); 67 blo(y, x, l); 68 } 69 return 0; 70 } 71 void init() { 72 t = 0; 73 memset(head, 0, sizeof(head)); 74 memset(c, 0, sizeof(c)); 75 memset(pr, 0, sizeof(pr)); 76 } 77 }; 78 int main() { 79 int _, n, m; 80 scanf("%d", &_); 81 while (_--) { 82 Blossom blossom; 83 blossom.init(); 84 scanf("%d%d", &n, &m); 85 tot = n * 2 + m; 86 for (int i = 1; i <= n; i++) { 87 scanf("%s", ch + 1); 88 blossom.add(i + m, i + m + n); 89 blossom.add(i + m + n, i + m); 90 for (int j = 1; j <= m; j++) 91 if (ch[j] - '0') { 92 blossom.add(j, i + m); 93 blossom.add(i + m, j); 94 blossom.add(j, i + m + n); 95 blossom.add(i + m + n, j); 96 } 97 } 98 int ans = 0; 99 for (int i = 1; i <= tot; i++) { 100 if (!blossom.c[i]) ans += blossom.aug(i); 101 } 102 printf("%d\n", ans - n); 103 } 104 return 0; 105 }
array
不难看出对于每次2操作,答案最大是n+1(因为每次更新是+10000000, 永远不会占用n+1,而且k是保证<=n的). 如果某个数字被进行过1操作, 那么就代表这个数字可以用于2类操作的查询,把这个数字加到set里.对于找2类询问的答案,第一种是从a[r+1,n]里找>=k的最小值(主席树实现),第二种是从这个set里找>=k的最小值(对set进行二分查找),取两者间最小值即可.
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 #include <bits/stdc++.h> 2 using namespace std; 3 const int maxn=200100; 4 struct node 5 { 6 int l,r,sum; 7 } hjt[maxn*40]; 8 int cnt,root[maxn*20],n,m,book[maxn]; 9 int a[maxn]; 10 set<int>s; 11 set<int>::iterator it; 12 void init() { 13 for (int i = 0; i <= n; i++) book[i] = 0; 14 s.clear(); 15 root[0] = 0; 16 cnt = 0; 17 for (int i = 0; i < maxn * 20; i++) hjt[i].l = hjt[i].r = hjt[i].sum = 0; 18 } 19 void insert(int l,int r,int pre,int &now,int p) 20 { 21 hjt[++cnt]=hjt[pre]; 22 now=cnt; 23 hjt[now].sum++; 24 if (l==r) 25 { 26 return; 27 } 28 int mid=(l+r)>>1; 29 if (p<=mid) 30 { 31 insert(l,mid,hjt[pre].l,hjt[now].l,p); 32 } 33 else 34 { 35 insert(mid+1,r,hjt[pre].r,hjt[now].r,p); 36 } 37 } 38 int query(int rt,int l,int r,int L,int R) { 39 if (R < L) return -1; 40 if (!rt) return -1; 41 if (!hjt[rt].sum) return -1; 42 if (l >= L && r <= R) { 43 if (l == r) 44 return l; 45 else { 46 int mid = (l + r) >> 1; 47 int res = -1; 48 if (L <= mid) res = query(hjt[rt].l, l, mid, L, R); 49 if (R > mid && res == -1) res = query(hjt[rt].r, mid + 1, r, L, R); 50 return res; 51 } 52 } 53 int mid = (l + r) >> 1; 54 int res = -1; 55 if (L <= mid) res = query(hjt[rt].l, l, mid, L, R); 56 if (R > mid && res == -1) res = query(hjt[rt].r, mid + 1, r, L, R); 57 return res; 58 } 59 60 int main() { 61 int _; 62 scanf("%d", &_); 63 while (_--) { 64 scanf("%d%d", &n, &m); 65 init(); 66 root[n + 1] = 0; 67 for (int i = 1; i <= n; i++) scanf("%d", &a[i]); 68 for (int i = n; i >= 1; i--) 69 insert(1, n, root[i + 1], root[i], a[i]); 70 int lastans = 0; 71 for (int i = 1; i <= m; i++) { 72 int id; 73 scanf("%d", &id); 74 if (id == 1) { 75 int t; 76 scanf("%d", &t); 77 int pos = t ^lastans; 78 if (book[pos]) continue; 79 book[pos] = 1; 80 s.insert(a[pos]); 81 } else { 82 int t1, t2; 83 scanf("%d%d", &t1, &t2); 84 int R = (t1 ^lastans) + 1; 85 int k = t2 ^lastans; 86 int ans = n + 1; 87 it = s.lower_bound(k); 88 if (it != s.end()) ans = *it; 89 if (R <= n) { 90 t1 = query(root[R], 1, n, k, n); 91 if (t1 != -1) ans = min(ans, t1); 92 } 93 printf("%d\n", ans); 94 lastans = ans; 95 } 96 } 97 } 98 return 0; 99 }
主席树(静态查询区间第k大)
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 #include <bits/stdc++.h> 2 3 using namespace std; 4 const int maxn=200100; 5 struct node 6 { 7 int l,r,sum; 8 } hjt[maxn*40]; 9 int cnt,root[maxn*40]; 10 vector<int>v; 11 int a[maxn]; 12 int getid(int x) 13 { 14 return lower_bound(v.begin(),v.end(),x)-v.begin()+1; 15 } 16 17 void insert(int l,int r,int pre,int &now,int p) 18 { 19 hjt[++cnt]=hjt[pre]; 20 now=cnt; 21 hjt[now].sum++; 22 if (l==r) 23 { 24 return; 25 } 26 int mid=(l+r)>>1; 27 if (p<=mid) 28 { 29 insert(l,mid,hjt[pre].l,hjt[now].l,p); 30 } 31 else 32 { 33 insert(mid+1,r,hjt[pre].r,hjt[now].r,p); 34 } 35 } 36 37 int query(int l,int r,int L,int R,int k) 38 { 39 if (l==r) 40 return l; 41 int mid=(l+r)>>1; 42 int tmp=hjt[hjt[R].l].sum-hjt[hjt[L].l].sum; 43 if (k<=tmp) 44 { 45 return query(l,mid,hjt[L].l,hjt[R].l,k); 46 } 47 else 48 { 49 return query(mid+1,r,hjt[L].r,hjt[R].r,k-tmp); 50 } 51 } 52 int main() 53 { 54 int n,m; 55 scanf("%d%d",&n,&m); 56 for (int i=1; i<=n; i++) 57 { 58 scanf("%d",&a[i]); 59 v.push_back(a[i]); 60 } 61 sort(v.begin(),v.end()); 62 v.erase(unique(v.begin(),v.end()),v.end()); 63 for (int i=1; i<=n; i++) 64 { 65 insert(1,n,root[i-1],root[i],getid(a[i])); 66 } 67 while (m--) 68 { 69 int l,r,k; 70 scanf("%d%d%d",&l,&r,&k); 71 printf("%d\n",v[query(1,n,root[l-1],root[r],k)-1]); 72 } 73 return 0; 74 }
最近公共祖先(LCA)
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int N=500010; 4 struct node 5 { 6 int n,t; 7 } e[N*2]; 8 int h[N],f[N][20],t,d[N],x,y; 9 void add(int u,int v) 10 { 11 t++; 12 e[t].t=v; 13 e[t].n=h[u]; 14 h[u]=t; 15 } 16 17 void dfs(int x,int fa) 18 { 19 d[x]=d[fa]+1; 20 f[x][0]=fa; 21 for (int i=1; (1<<i)<=d[x]; i++) 22 { 23 f[x][i]=f[f[x][i-1]][i-1]; 24 } 25 for (int i=h[x]; i; i=e[i].n) 26 { 27 if (e[i].t!=fa) 28 { 29 dfs(e[i].t,x); 30 } 31 } 32 } 33 34 int lca(int x,int y) 35 { 36 if (d[x]<d[y]) 37 { 38 swap(x,y); 39 } 40 int h=d[x]-d[y],k=0; 41 while (h) 42 { 43 if (h&1) 44 { 45 x=f[x][k]; 46 } 47 h>>=1; 48 k++; 49 } 50 if (x==y) 51 { 52 return x; 53 } 54 for (int k=19; k>=0; k--) 55 { 56 if (f[x][k]!=f[y][k]) 57 { 58 x=f[x][k]; 59 y=f[y][k]; 60 } 61 } 62 return f[x][0]; 63 } 64 65 int n,m,s; 66 int main() 67 { 68 scanf("%d%d%d",&n,&m,&s); 69 for (int i=1; i<n; i++) 70 { 71 scanf("%d%d",&x,&y); 72 add(x,y); 73 add(y,x); 74 } 75 dfs(s,0); 76 for (int i=1;i<=m;i++){ 77 scanf("%d%d",&x,&y); 78 printf("%d\n",lca(x,y)); 79 } 80 }
LCT
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 #include <iostream> 2 #include <ctime> 3 #include <cstdio> 4 #include <cctype> 5 namespace FastIO 6 { 7 char buf[1 << 21], buf2[1 << 21], a[20], *p1 = buf, *p2 = buf, hh = '\n'; 8 int p, p3 = -1; 9 void read() {} 10 void print() {} 11 inline int getc() 12 { 13 return p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1 << 21, stdin), p1 == p2) ? EOF : *p1++; 14 } 15 inline void flush() 16 { 17 fwrite(buf2, 1, p3 + 1, stdout), p3 = -1; 18 } 19 template <typename T, typename... T2> 20 inline void read(T &x, T2 &... oth) 21 { 22 int f = 0; 23 x = 0; 24 char ch = getc(); 25 while (!isdigit(ch)) 26 { 27 if (ch == '-') 28 f = 1; 29 ch = getc(); 30 } 31 while (isdigit(ch)) 32 { 33 x = x * 10 + ch - 48; 34 ch = getc(); 35 } 36 x = f ? -x : x; 37 read(oth...); 38 } 39 template <typename T, typename... T2> 40 inline void print(T x, T2... oth) 41 { 42 if (p3 > 1 << 20) 43 flush(); 44 if (x < 0) 45 buf2[++p3] = 45, x = -x; 46 do 47 { 48 a[++p] = x % 10 + 48; 49 } while (x /= 10); 50 do 51 { 52 buf2[++p3] = a[p]; 53 } while (--p); 54 buf2[++p3] = hh; 55 print(oth...); 56 } 57 } // namespace FastIO 58 #define read FastIO::read 59 #define print FastIO::print 60 //====================================== 61 const int maxn = 1e5+5; 62 struct Node 63 { 64 int fa,ch[2],val,res; //res是异或结果 65 bool tag; //翻转懒标记 66 }spl[maxn]; 67 //因为被毒瘤数据卡得TLE一个点,所以全部换成了#define。都是字面意思 68 #define ls(x) (spl[x].ch[0]) 69 #define rs(x) (spl[x].ch[1]) 70 #define fa(x) (spl[x].fa) 71 #define ident(x,f) (rs(f)==x) //和下面的connect都是Splay的辅助函数 72 #define connect(x,f,s) spl[fa(x)=f].ch[s]=x 73 #define update(x) spl[x].res=spl[ls(x)].res^spl[rs(x)].res^spl[x].val 74 #define ntroot(x) (ls(fa(x))==x||rs(fa(x))==x) //判断结点是否为Splay的根 75 #define reverse(x) std::swap(ls(x),rs(x)),spl[x].tag^=1 76 inline void pushdw(int x) //懒标记下传 77 { 78 if(spl[x].tag) 79 { 80 if(ls(x)) reverse(ls(x)); 81 if(rs(x)) reverse(rs(x)); 82 } 83 spl[x].tag=0; 84 } 85 void pushall(int x) //头递归,从上到下下传所有懒标记 86 { 87 if(ntroot(x)) pushall(fa(x)); 88 pushdw(x); 89 } 90 inline void rotate(int x) //Splay基操 91 { 92 int f=fa(x),ff=fa(f),k=ident(x,f); 93 connect(spl[x].ch[k^1],f,k); 94 fa(x)=ff; 95 if(ntroot(f)) spl[ff].ch[ident(f,ff)]=x;//※重要,不能忘记判断,关系到虚实边 96 connect(f,x,k^1); 97 update(f),update(x); 98 } 99 inline void splaying(int x) //Splay基操,都是伸展到根结点 100 { 101 pushall(x); //要先把上面的懒标记全都下传 102 while(ntroot(x)) 103 { 104 int f=fa(x),ff=fa(f); 105 if(ntroot(f)) ident(f,ff)^ident(x,f)?rotate(x):rotate(f); 106 rotate(x); 107 } 108 } 109 inline void access(int x) //从x到原树根结点拉一条实链 110 { 111 for(int y=0;x;x=fa(y=x)) //y为上一个Splay的根 112 { 113 splaying(x); //伸展到当前Splay的根 114 rs(x)=y; //右儿子连上上一个Splay的根 115 update(x); //别忘更新>﹏< 116 } 117 } 118 inline void mkroot(int x) //给原树换根 119 { 120 access(x); //先拉实链,拉好后x一定在Splay的最右(深度最大) 121 splaying(x); //再伸展,伸展后x必定没有右儿子 122 reverse(x); //翻转拉出来这条实链,使深度顺序翻转 123 } 124 inline int findroot(int x) //寻找结点在原树的根 125 { 126 access(x); //先拉实链 127 splaying(x); //再伸展 128 while(ls(x)) //因为根结点必定深度最小,所以不停往左找就OK了 129 { 130 pushdw(x); //别忘了下传,第一个儿子是没问题的但是第二个往后…… 131 x=ls(x); 132 } 133 splaying(x); //用来保证时间复杂度,防止卡链 134 return x; 135 } 136 inline void link(int x,int y) //连边,不保证数据合法 137 { 138 mkroot(x); //换根 139 if(findroot(y)==x) return; //如果y所在的树的根结点是x,那说明两者在一棵树上 140 fa(x)=y; 141 } 142 inline void cut(int x,int y) //断边,不保证数据合法 143 { 144 mkroot(x); //换根 145 //? 如果y跟x不在一棵树上 or x和y之间不是紧紧挨着的,return 146 //! 注意这里findroot后由于保证复杂度的一句伸展,导致刚才被换成根的x成为了Splay的根结点 147 //* 又因为x在原树中是根结点,深度最小,所以在Splay中一定是x为根结点y为其右儿子 148 if(findroot(y)!=x||fa(y)!=x||ls(y)) return; 149 fa(y)=rs(x)=0; //双向断边 150 update(x); //别忘更新>﹏< 151 } 152 inline void split(int x,int y) //把x--y的路径拆出来 153 { 154 mkroot(x); //换根 155 access(y); //拉实链 156 splaying(y); //伸展 157 //? 此时y必定没有右儿子且左儿子是一条到x的实链,所以访问y就可以作任何关于这条链的操作了 158 } 159 int main(int argc, char const *argv[]) 160 { 161 #ifndef ONLINE_JUDGE 162 freopen("in.in", "r", stdin); 163 freopen("out.out", "w", stdout); 164 #endif 165 clock_t c1 = clock(); 166 //====================================== 167 int n,m; 168 read(n,m); 169 //? 刚开始的时候所有点之间都没连着 170 for(int i=1;i<=n;i++) read(spl[i].val); 171 while(m--) 172 { 173 int opt,x,y; 174 read(opt,x,y); 175 switch(opt) 176 { 177 case 0: 178 split(x,y); 179 print(spl[y].res); //访问y就相当于访问这条链了 180 break; 181 case 1: 182 link(x,y); 183 break; 184 case 2: 185 cut(x,y); 186 break; 187 case 3: 188 splaying(x); //注意要先伸展到根,否则会很麻烦 189 spl[x].val=y; 190 update(x); //不更新也没啥问题,加不加都行 191 break; 192 } 193 } 194 //====================================== 195 FastIO::flush(); 196 std::cerr << "Time:" << clock() - c1 << "ms" << std::endl; 197 return 0; 198 }
可持久化并查集
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 #include <iostream> 2 #include <ctime> 3 #include <cstdio> 4 #include <cctype> 5 namespace FastIO 6 { 7 char buf[1 << 21], buf2[1 << 21], a[20], *p1 = buf, *p2 = buf, hh = '\n'; 8 int p, p3 = -1; 9 void read() {} 10 void print() {} 11 inline int getc() 12 { 13 return p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1 << 21, stdin), p1 == p2) ? EOF : *p1++; 14 } 15 inline void flush() 16 { 17 fwrite(buf2, 1, p3 + 1, stdout), p3 = -1; 18 } 19 template <typename T, typename... T2> 20 inline void read(T &x, T2 &... oth) 21 { 22 int f = 0; 23 x = 0; 24 char ch = getc(); 25 while (!isdigit(ch)) 26 { 27 if (ch == '-') 28 f = 1; 29 ch = getc(); 30 } 31 while (isdigit(ch)) 32 { 33 x = x * 10 + ch - 48; 34 ch = getc(); 35 } 36 x = f ? -x : x; 37 read(oth...); 38 } 39 template <typename T, typename... T2> 40 inline void print(T x, T2... oth) 41 { 42 if (p3 > 1 << 20) 43 flush(); 44 if (x < 0) 45 buf2[++p3] = 45, x = -x; 46 do 47 { 48 a[++p] = x % 10 + 48; 49 } while (x /= 10); 50 do 51 { 52 buf2[++p3] = a[p]; 53 } while (--p); 54 buf2[++p3] = hh; 55 print(oth...); 56 } 57 } // namespace FastIO 58 #define read FastIO::read 59 #define print FastIO::print 60 //====================================== 61 const int maxn = 2e5+5; 62 int n; 63 struct Node 64 { 65 int l,r,val; 66 }hjt[maxn*40*2]; 67 int cnt,rootfa[maxn],rootdep[maxn],tot; 68 void build(int l,int r,int &now) 69 { 70 now = ++cnt; 71 if(l==r) 72 { 73 hjt[now].val=++tot; 74 return; 75 } 76 int m = (l+r)>>1; 77 build(l,m,hjt[now].l); 78 build(m+1,r,hjt[now].r); 79 } 80 void modify(int l,int r,int ver,int &now,int pos,int val) 81 { 82 hjt[now=++cnt]=hjt[ver]; 83 if(l==r) 84 { 85 hjt[now].val=val; 86 return; 87 } 88 int m = (l+r)>>1; 89 if(pos<=m) modify(l,m,hjt[ver].l,hjt[now].l,pos,val); 90 else modify(m+1,r,hjt[ver].r,hjt[now].r,pos,val); 91 } 92 int query(int l,int r,int now,int pos) 93 { 94 if(l==r) return hjt[now].val; 95 int m = (l+r)>>1; 96 if(pos<=m) return query(l,m,hjt[now].l,pos); 97 else return query(m+1,r,hjt[now].r,pos); 98 } 99 int find(int ver,int x) 100 { 101 int fx = query(1,n,rootfa[ver],x); 102 return fx==x?x:find(ver,fx); 103 } 104 void merge(int ver,int x,int y) 105 { 106 x = find(ver-1,x); //ver-1 107 y = find(ver-1,y); 108 if(x==y) 109 { 110 rootfa[ver]=rootfa[ver-1]; 111 rootdep[ver]=rootdep[ver-1]; 112 } 113 else 114 { 115 int depx = query(1,n,rootdep[ver-1],x); 116 int depy = query(1,n,rootdep[ver-1],y); 117 if(depx<depy) 118 { 119 modify(1,n,rootfa[ver-1],rootfa[ver],x,y); 120 rootdep[ver]=rootdep[ver-1]; 121 } 122 else if(depx>depy) 123 { 124 modify(1,n,rootfa[ver-1],rootfa[ver],y,x); 125 rootdep[ver]=rootdep[ver-1]; 126 } 127 else 128 { 129 modify(1,n,rootfa[ver-1],rootfa[ver],x,y); 130 modify(1,n,rootdep[ver-1],rootdep[ver],y,depy+1); 131 } 132 } 133 } 134 int main(int argc, char const *argv[]) 135 { 136 #ifndef ONLINE_JUDGE 137 freopen("in.in", "r", stdin); 138 freopen("out.out", "w", stdout); 139 #endif 140 clock_t c1 = clock(); 141 //====================================== 142 int m; 143 read(n,m); 144 build(1,n,rootfa[0]); 145 for(int ver=1;ver<=m;ver++) 146 { 147 int opt,x,y; 148 read(opt); 149 switch(opt) 150 { 151 case 1: 152 read(x,y); 153 merge(ver,x,y); 154 break; 155 case 2: 156 read(x); 157 rootfa[ver]=rootfa[x]; 158 rootdep[ver]=rootdep[x]; 159 break; 160 case 3: 161 read(x,y); 162 rootfa[ver]=rootfa[ver-1]; 163 rootdep[ver]=rootdep[ver-1]; 164 int fx = find(ver,x); 165 int fy = find(ver,y); 166 print(fx==fy?1:0); 167 break; 168 } 169 } 170 //====================================== 171 FastIO::flush(); 172 std::cerr << "Time:" << clock() - c1 << "ms" << std::endl; 173 return 0; 174 }
可持久化数组
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 #include <iostream> 2 #include <ctime> 3 #include <cstdio> 4 #include <cctype> 5 namespace FastIO 6 { 7 char buf[1 << 21], buf2[1 << 21], a[20], *p1 = buf, *p2 = buf, hh = '\n'; 8 int p, p3 = -1; 9 void read() {} 10 void print() {} 11 inline int getc() 12 { 13 return p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1 << 21, stdin), p1 == p2) ? EOF : *p1++; 14 } 15 inline void flush() 16 { 17 fwrite(buf2, 1, p3 + 1, stdout), p3 = -1; 18 } 19 template <typename T, typename... T2> 20 inline void read(T &x, T2 &... oth) 21 { 22 int f = 0; 23 x = 0; 24 char ch = getc(); 25 while (!isdigit(ch)) 26 { 27 if (ch == '-') 28 f = 1; 29 ch = getc(); 30 } 31 while (isdigit(ch)) 32 { 33 x = x * 10 + ch - 48; 34 ch = getc(); 35 } 36 x = f ? -x : x; 37 read(oth...); 38 } 39 template <typename T, typename... T2> 40 inline void print(T x, T2... oth) 41 { 42 if (p3 > 1 << 20) 43 flush(); 44 if (x < 0) 45 buf2[++p3] = 45, x = -x; 46 do 47 { 48 a[++p] = x % 10 + 48; 49 } while (x /= 10); 50 do 51 { 52 buf2[++p3] = a[p]; 53 } while (--p); 54 buf2[++p3] = hh; 55 print(oth...); 56 } 57 } // namespace FastIO 58 #define read FastIO::read 59 #define print FastIO::print 60 //====================================== 61 const int maxn = 1e6+5; 62 int a[maxn]; 63 struct Node 64 { 65 int l,r,val; 66 }hjt[maxn*40]; 67 int cnt,root[maxn]; 68 void build(int l,int r,int &now) 69 { 70 now=++cnt; 71 if(l==r) 72 { 73 hjt[now].val=a[l]; 74 return; 75 } 76 int m = (l+r)>>1; 77 build(l,m,hjt[now].l); 78 build(m+1,r,hjt[now].r); 79 } 80 void modify(int l,int r,int ver,int &now,int &pos,int &num) 81 { 82 hjt[now=++cnt]=hjt[ver]; 83 if(l==r) 84 { 85 hjt[now].val=num; 86 return; 87 } 88 int m = (l+r)>>1; 89 if(pos<=m) modify(l,m,hjt[ver].l,hjt[now].l,pos,num); 90 else modify(m+1,r,hjt[ver].r,hjt[now].r,pos,num); 91 } 92 int query(int l,int r,int now,int &pos) 93 { 94 if(l==r) return hjt[now].val; 95 int m = (l+r)>>1; 96 if(pos<=m) return query(l,m,hjt[now].l,pos); 97 else return query(m+1,r,hjt[now].r,pos); 98 } 99 int main(int argc, char const *argv[]) 100 { 101 #ifndef ONLINE_JUDGE 102 freopen("in.in", "r", stdin); 103 freopen("out.out", "w", stdout); 104 #endif 105 clock_t c1 = clock(); 106 //====================================== 107 int n,m,ver,opt,x,y; 108 read(n,m); 109 for(int i=1;i<=n;i++) read(a[i]); 110 build(1,n,root[0]); 111 for(int i=1;i<=m;i++) 112 { 113 read(ver,opt); 114 switch(opt) 115 { 116 case 1: 117 read(x,y); 118 modify(1,n,root[ver],root[i],x,y); 119 break; 120 case 2: 121 read(x); 122 print(query(1,n,root[ver],x)); 123 root[i]=root[ver]; 124 break; 125 } 126 } 127 //====================================== 128 FastIO::flush(); 129 std::cerr << "Time:" << clock() - c1 << "ms" << std::endl; 130 return 0; 131 }
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 typedef long long ll; 5 6 const int maxn=1e5+10; 7 const ll inf=0x3f3f3f3f; 8 9 int n,m,fa[maxn],val1,val2,dp[3][maxn][20],t,head[maxn],f[maxn][20],deep[maxn]; 10 ll ans,ans_max; 11 struct edge1 { 12 int v, next,w; 13 }e[maxn*2]; 14 struct edge2 { 15 int u, v, w, vis; 16 17 bool operator<(const edge2 &b) const { 18 return w < b.w; 19 } 20 }a[maxn*3]; 21 22 void add(int u,int v,int w) { 23 t++; 24 e[t].v = v; 25 e[t].w = w; 26 e[t].next = head[u]; 27 head[u] = t; 28 } 29 30 int fin(int x){ 31 return x==fa[x]?x:fa[x]=fin(fa[x]); 32 } 33 void Kruskal() { 34 sort(a + 1, a + m + 1); 35 for (int i = 1; i <= m; i++) { 36 int u = fin(a[i].u); 37 int v = fin(a[i].v); 38 if (u == v) continue; 39 fa[u] = v; 40 a[i].vis = 1; 41 ans += 1ll*a[i].w; 42 add(a[i].u, a[i].v, a[i].w); 43 add(a[i].v, a[i].u, a[i].w); 44 } 45 } 46 47 void dfs(int u,int fa) { 48 49 for (int i = 1; (1 << i) <= deep[u]; i++) { 50 f[u][i] = f[f[u][i - 1]][i - 1]; 51 52 dp[0][u][i] = max(dp[0][u][i - 1], dp[0][f[u][i - 1]][i - 1]); 53 if (dp[0][u][i - 1] != dp[0][f[u][i - 1]][i - 1]) { 54 dp[1][u][i] = min(dp[0][u][i - 1], dp[0][f[u][i - 1]][i - 1]); 55 dp[1][u][i] = max(dp[1][u][i], dp[1][u][i - 1]); 56 dp[1][u][i] = max(dp[1][u][i], dp[1][f[u][i - 1]][i - 1]); 57 } 58 else 59 dp[1][u][i] = max(dp[1][u][i - 1], dp[1][f[u][i - 1]][i - 1]); 60 } 61 62 for (int i = head[u]; i; i = e[i].next) { 63 int v = e[i].v; 64 if (v == fa) continue; 65 f[v][0] = u; 66 dp[0][v][0] = e[i].w; 67 dp[1][v][0] = -inf; 68 deep[v] = deep[u] + 1; 69 dfs(v, u); 70 } 71 } 72 73 void update2(int x) { 74 if (x > val1) { 75 val2 = val1; 76 val1 = x; 77 } else if (x > val2 && x != val1) 78 val2 = x; 79 } 80 81 void update(int x,int i) { 82 update2(dp[0][x][i]); 83 update2(dp[1][x][i]); 84 } 85 86 void lca(int x,int y) { 87 val1 = val2 = -inf; 88 if (deep[x] < deep[y]) { 89 swap(x, y); 90 } 91 int h = deep[x] - deep[y], k = 0; 92 while (h) { 93 94 if (h & 1) { 95 update(x,k); 96 x = f[x][k]; 97 } 98 h >>= 1; 99 k++; 100 } 101 if (x == y) return; 102 for (int k = 19; k >= 0; k--) { 103 if (f[x][k] != f[y][k]) { 104 update(x, k); 105 x = f[x][k]; 106 update(y, k); 107 y = f[y][k]; 108 } 109 } 110 update(x,0); 111 update(y,0); 112 } 113 114 int main() { 115 scanf("%d%d", &n, &m); 116 for (int i=1;i<=n;i++){ 117 fa[i]=i; 118 } 119 for (int i = 1; i <= m; i++) { 120 scanf("%d%d%d", &a[i].u, &a[i].v, &a[i].w); 121 } 122 Kruskal(); 123 dfs(1, 0); 124 ans_max = 0x3f3f3f3f3f3f3f3f; 125 for (int i = 1; i <= m; i++) { 126 if (!a[i].vis) { 127 lca(a[i].u, a[i].v); 128 if (val1 != a[i].w) 129 ans_max = min(ans_max, ans - val1 + a[i].w); 130 else ans_max = min(ans_max, ans - val2 + a[i].w); 131 } 132 } 133 printf("%lld\n", ans_max); 134 }
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 #include <bits/stdc++.h> 2 3 using namespace std; 4 const int maxn=20010; 5 int cnt[maxn],t,tim,sta[maxn],dfn[maxn],low[maxn],top,head[maxn],flag,root; 6 struct edge{ 7 int to,next; 8 }e[maxn*5]; 9 void add(int u,int v){ 10 t++; 11 e[t].to=v; 12 e[t].next=head[u]; 13 head[u]=t; 14 } 15 16 void tarjan(int u) { 17 low[u] = dfn[u] = ++tim; 18 int flag=0; 19 for (int i = head[u]; i; i = e[i].next) { 20 int v = e[i].to; 21 if (!dfn[v]) {//不曾访问过,也就是没有标记,可以认为是儿子节点了 22 tarjan(v);//访问儿子节点y,并且设置边为当前边 23 low[u] = min(low[u], low[v]);//看看能不能更新,也就是定义中的,subtree(x)中的节点最小值为low[x] 24 //subtree(x)表示搜索树中以x节点为根的子树节点集合 25 if (low[v] >= dfn[u]) {//这就是割点的判定 26 flag++;//割点数量++ 27 if (u != root || flag > 1) //不能是根节点,或者说是根节点,但是有至少两个子树节点是割点 28 cnt[u] = 1; 29 } 30 } else 31 low[u] = min(low[u], dfn[v]);//第二类定义,也就是通过1跳不在搜索树上的边,能够抵达subtree(x)的节点 32 } 33 } 34 int main() { 35 int n,m, ans=0; 36 scanf("%d%d", &n, &m); 37 for (int i = 1, u, v; i <= m; i++) { 38 scanf("%d%d", &u, &v); 39 add(u, v); 40 add(v, u); 41 } 42 for (int i = 1; i <= n; i++) { 43 if (!dfn[i]) { //一个无向图,可能由多个搜索树构成 44 root = i; 45 tarjan(i); 46 } 47 } 48 for (int i = 1; i <= n; i++) {//统计割点个数 49 if (cnt[i]) ans++; 50 } 51 int num=0; 52 printf("%d\n", ans); 53 for (int i = 1; i <= n; i++) { 54 if (cnt[i]) { 55 num++; 56 printf("%d", i); 57 if (num < ans) printf(" "); else printf("\n"); 58 }//顺序遍历,康康哪些点是割点 59 } 60 return 0; 61 }
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 #include <bits/stdc++.h> 2 3 using namespace std; 4 const int maxn=100010; 5 int cnt[maxn],t,tim,bridge[maxn*6],dfn[maxn],low[maxn],top,head[maxn],flag,root; 6 struct edge{ 7 int to,next; 8 }e[maxn*6]; 9 void add(int u,int v){ 10 t++; 11 e[t].to=v; 12 e[t].next=head[u]; 13 head[u]=t; 14 } 15 16 void tarjan(int u,int edge) { 17 low[u] = dfn[u] = ++tim; 18 for (int i = head[u]; i; i = e[i].next) { 19 int v = e[i].to; 20 if (!dfn[v]) {//不曾访问过,也就是没有标记,可以认为是儿子节点了 21 tarjan(v, i);//访问儿子节点y,并且设置边为当前边 22 low[u] = min(low[u], low[v]);//看看能不能更新,也就是定义中的,subtree(x)中的节点最小值为low[x] 23 //subtree(x)表示搜索树中以x节点为根的子树节点集合 24 if (low[v] > dfn[u]) //这就是割点的判定 25 bridge[i] = bridge[i ^ 1] = 1;//重边也是桥 26 } else if (i != (edge ^ 1)) 27 low[u] = min(low[u], dfn[v]);//第二类定义,也就是通过1跳不在搜索树上的边,能够抵达subtree(x)的节点 28 } 29 } 30 int main() { 31 t = 1; 32 int n, m, ans = 0; 33 scanf("%d%d", &n, &m); 34 for (int i = 1, u, v; i <= m; i++) { 35 scanf("%d%d", &u, &v); 36 add(u, v); 37 add(v, u); 38 } 39 for (int i = 1; i <= n; i++) { 40 if (!dfn[i]) //一个无向图,可能由多个搜索树构成 41 tarjan(i, 0); 42 } 43 int num=0; 44 for (int i = 2; i <= t; i+=2) { 45 if (bridge[i]) 46 num++; 47 } 48 printf("%d\n",m-num); 49 }
Tarjan
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 void tarjan(int u) { 2 low[u] = dfn[u] = ++index; 3 stack[top++] = u; 4 for (int i = head[u]; i; i = e[i].next) { 5 int v = e[i].to; 6 if (!dfn[v]) { 7 tarjan(v); 8 low[u] = min(low[u], low[v]); 9 } else { 10 if (!blong[v]) { 11 low[u] = min(low[u], dfn[v]); 12 } 13 } 14 } 15 if (dfn[u] == low[u]) { 16 scc++; 17 for (;;) { 18 v = stack[--top]; 19 belong[v] = scc; 20 if (v == u) break; 21 } 22 } 23 }
动态查询区间第k大
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 #include <bits/stdc++.h> 2 3 using namespace std; 4 5 const int maxn=250000; 6 const int M=250000*400; 7 int n,q,m,tot; 8 int a[maxn],t[maxn]; 9 int T[maxn],lson[M],rson[M],c[M]; 10 int S[maxn]; 11 struct Query{ 12 int kind; 13 int l,r,k; 14 }query[100100]; 15 void init_hash(int k){ 16 sort(t,t+k); 17 m=unique(t,t+k)-t; 18 } 19 int hash1(int x){ 20 return lower_bound(t,t+m,x)-t; 21 } 22 23 int build(int l,int r) { 24 int root = tot++; 25 c[root] = 0; 26 if (l != r) { 27 int mid = (l + r) >> 1; 28 lson[root] = build(l, mid); 29 rson[root] = build(mid + 1, r); 30 } 31 return root; 32 } 33 34 int insert(int root,int pos,int val) { 35 int newroot = tot++, tmp = newroot; 36 int l = 0, r = m - 1; 37 c[newroot] = c[root] + val; 38 while (l < r) { 39 int mid = (l + r) >> 1; 40 if (pos <= mid) { 41 lson[newroot] = tot++; 42 rson[newroot] = rson[root]; 43 newroot = lson[newroot]; 44 root = lson[root]; 45 r = mid; 46 } else { 47 rson[newroot] = tot++; 48 lson[newroot] = lson[root]; 49 newroot = rson[newroot]; 50 root = rson[root]; 51 l = mid + 1; 52 } 53 c[newroot] = c[root] + val; 54 } 55 return tmp; 56 } 57 58 int lowbit(int x) { 59 return x & -x; 60 } 61 62 int use[maxn]; 63 64 int sum(int x) { 65 int ret = 0; 66 while (x) { 67 ret += c[lson[use[x]]]; 68 x -= lowbit(x); 69 } 70 return ret; 71 } 72 73 int Query(int left,int right,int k) { 74 int left_root = T[left - 1]; 75 int right_root = T[right]; 76 int l = 0, r = m - 1; 77 for (int i = left - 1; i; i -= lowbit(i)) use[i] = S[i]; 78 for (int i = right; i; i -= lowbit(i)) use[i] = S[i]; 79 while (l < r) { 80 int mid = (l + r) >> 1; 81 int tmp = sum(right) - sum(left - 1) + c[lson[right_root]] - c[lson[left_root]]; 82 if (tmp >= k) { 83 r = mid; 84 for (int i = left - 1; i; i -= lowbit(i)) use[i] = lson[use[i]]; 85 for (int i = right; i; i -= lowbit(i)) use[i] = lson[use[i]]; 86 left_root = lson[left_root]; 87 right_root = lson[right_root]; 88 } else { 89 l = mid + 1; 90 k -= tmp; 91 for (int i = left - 1; i; i -= lowbit(i)) use[i] = rson[use[i]]; 92 for (int i = right; i; i -= lowbit(i)) use[i] = rson[use[i]]; 93 left_root = rson[left_root]; 94 right_root = rson[right_root]; 95 } 96 } 97 return l; 98 } 99 100 void Modify(int x,int p,int d) { 101 while (x <= n) { 102 S[x] = insert(S[x], p, d); 103 x += lowbit(x); 104 } 105 } 106 107 int main() { 108 scanf("%d%d", &n, &q); 109 for (int i = 1; i <= n; i++) { 110 scanf("%d", &a[i]); 111 t[m++] = a[i]; 112 } 113 char op[10]; 114 for (int i = 0; i < q; i++) { 115 scanf("%s", op); 116 if (op[0] == 'Q') { 117 query[i].kind = 0; 118 scanf("%d%d%d", &query[i].l, &query[i].r, &query[i].k); 119 } else { 120 query[i].kind = 1; 121 scanf("%d%d", &query[i].l, &query[i].r); 122 t[m++] = query[i].r; 123 } 124 } 125 init_hash(m); 126 T[0] = build(0, m - 1); 127 for (int i = 1; i <= n; i++) { 128 T[i] = insert(T[i - 1], hash1(a[i]), 1); 129 } 130 for (int i = 1; i <= n; i++) { 131 S[i] = T[0]; 132 } 133 for (int i = 0; i < q; i++) { 134 if (query[i].kind == 0) { 135 printf("%d\n", t[Query(query[i].l, query[i].r, query[i].k)]); 136 } else { 137 Modify(query[i].l, hash1(a[query[i].l]), -1); 138 Modify(query[i].l, hash1(query[i].r), 1); 139 a[query[i].l] = query[i].r; 140 } 141 } 142 return 0; 143 }