HDU 5333 Undirected Graph【LCT+BIT】
来源:互联网 发布:霸道总裁 知乎 编辑:程序博客网 时间:2024/06/01 08:11
LCT:
每次操作相当于只把区间
思路:
把操作排序后,对于区间
那么,答案==
求区间
假设当前的连通分量
这棵树上所有
如果当前联通分量是一棵树+一条边的话, 那么,如果树中有
考虑到删掉的边的单调性,即如果对于一棵树加入一条新的边
也就是说v’这条边就算在之后的操作中会被删掉也不会对答案产生影响,因此删掉这条边,并且将新边加入此树。
故区间
前者可以用LCT+并查集维护,后者可以用树状数组维护。
对于当前新加入的边
否则的话, 将u所在的LCT中
(代码来源)
#pragma comment(linker, "/STACK:1024000000")#include <stdio.h>#include <string.h>#include <map>#include <algorithm>using namespace std ;typedef long long LL ;#define clr( a , x ) memset ( a , x , sizeof a )#define ls ( o << 1 )#define rs ( o << 1 | 1 )#define lson ls , l , m#define rson rs , m + 1 , r#define root 1 , 1 , n#define mid ( ( l + r ) >> 1 )const int MAXN = 100005 ;const int MAXE = 200005 ;const int INF = 0x3f3f3f3f ;struct Edge { int v , idx , n ; Edge () {} Edge ( int v , int idx , int n ) : v ( v ) , idx ( idx ) , n ( n ) {}} ;struct Node* null ;struct Node { Node* c[2] ; Node* f ; bool flip ; int minv , val ; int eidx , idx ; void newnode ( int v , int i ) { c[0] = c[1] = f = null ; minv = val = v ; eidx = idx = i ; flip = 0 ; } void rev () { if ( this == null ) return ; swap ( c[0] , c[1] ) ; flip ^= 1 ; } void up () { if ( this == null ) return ; if ( val <= c[0]->minv && val <= c[1]->minv ) { minv = val ; eidx = idx ; } else if ( c[0]->minv <= c[1]->minv && c[0]->minv <= val ) { minv = c[0]->minv ; eidx = c[0]->eidx ; } else { minv = c[1]->minv ; eidx = c[1]->eidx ; } } void down () { if ( this == null ) return ; if ( flip ) { c[0]->rev () ; c[1]->rev () ; flip = 0 ; } } bool is_root () { return f == null || f->c[0] != this && f->c[1] != this ; } void sign_down () { if ( !is_root () ) f->sign_down () ; down () ; } void setc ( Node* o , int d ) { c[d] = o ; o->f = this ; } void rot ( int d ) { Node* p = f ; Node* g = f->f ; p->setc ( c[d] , !d ) ; if ( !p->is_root () ) g->setc ( this , f == g->c[1] ) ; else f = g ; setc ( p , d ) ; p->up () ; } void splay () { sign_down () ; while ( !is_root () ) { if ( f->is_root () ) rot ( this == f->c[0] ) ; else { if ( f == f->f->c[0] ) { if ( this == f->c[0] ) f->rot ( 1 ) , rot ( 1 ) ; else rot ( 0 ) , rot ( 1 ) ; } else { if ( this == f->c[1] ) f->rot ( 0 ) , rot ( 0 ) ; else rot ( 1 ) , rot ( 0 ) ; } } } up () ; } void access () { Node* o = this ; for ( Node* x = null ; o != null ; x = o , o = o->f ) { o->splay () ; o->setc ( x , 1 ) ; o->up () ; } splay () ; } void make_root () { access () ; rev () ; } void link ( Node* o ) { make_root () ; f = o ; } void cut () { access () ; c[0] = c[0]->f = null ; up () ; } void cut ( Node* o ) { make_root () ; o->cut () ; } int get_min ( Node* o ) { make_root () ; o->access () ; return o->eidx ; } } ;Node pool[MAXN + MAXE] ;Node* cur ;Node* node[MAXN] ;Node* edge[MAXE] ;Edge E[MAXE + MAXN] ;int H[MAXN] , Q[MAXN] , cntE ;int U[MAXE] , V[MAXE] ;int ans[MAXN] ;int p[MAXN] ;int c[MAXN] ;int n , m , q ;int find ( int x ) { return p[x] == x ? x : ( p[x] = find ( p[x] ) ) ;}void init ( int n ) { cntE = 0 ; cur = pool ; cur->newnode ( INF , -1 ) ; null = cur ++ ; for ( int i = 1 ; i <= n ; ++ i ) { p[i] = i ; H[i] = -1 ; Q[i] = -1 ; c[i] = 0 ; cur->newnode ( INF , -1 ) ; node[i] = cur ++ ; }}void addedge ( int u , int v , int idx , int H[] ) { E[cntE] = Edge ( v , idx , H[u] ) ; H[u] = cntE ++ ;}void add ( int x , int v ) { for ( ; x <= n ; x += x & -x ) c[x] += v ;}int sum ( int x , int ans = 0 ) { for ( ; x > 0 ; x -= x & -x ) ans += c[x] ; return ans ;}void scanf ( int& x , char c = 0 ) { while ( ( c = getchar () ) < '0' ) ; x = c - '0' ; while ( ( c = getchar () ) >= '0' ) x = x * 10 + c - '0' ;}void solve () { int cnt = 0 ; int u , v ; init ( n ) ; for ( int i = 1 ; i <= n ; ++ i ) add ( i , -1 ) ; for ( int i = 0 ; i < m ; ++ i ) { scanf ( "%d%d" , &u , &v ) ; if ( u == v ) continue ; if ( u < v ) swap ( u , v ) ; addedge ( u , v , i , H ) ; U[i] = u ; V[i] = v ; cur->newnode ( v , i ) ; edge[i] = cur ++ ; } for ( int i = 0 ; i < q ; ++ i ) { scanf ( "%d%d" , &u , &v ) ; addedge ( v , u , i , Q ) ; } for ( int i = 1 ; i <= n ; ++ i ) { ++ cnt ; for ( int j = H[i] ; ~j ; j = E[j].n ) { int v = E[j].v , idx = E[j].idx ; if ( v == i ) continue ; int x = find ( i ) ; int y = find ( v ) ; if ( x != y ) { -- cnt ; p[x] = y ; edge[idx]->link ( node[i] ) ; edge[idx]->link ( node[v] ) ; add ( v , 1 ) ; } else { int eidx = node[i]->get_min ( node[v] ) ; if ( V[eidx] >= v ) continue ; edge[eidx]->cut ( node[U[eidx]] ) ; edge[eidx]->cut ( node[V[eidx]] ) ; add ( V[eidx] , -1 ) ; edge[idx]->link ( node[i] ) ; edge[idx]->link ( node[v] ) ; add ( v , 1 ) ; } } for ( int j = Q[i] ; ~j ; j = E[j].n ) { int v = E[j].v , idx = E[j].idx ; ans[idx] = cnt + sum ( v - 1 ) + n - i + v - 1 ; } } for ( int i = 0 ; i < q ; ++ i ) { printf ( "%d\n" , ans[i] ) ; }}int main () { while ( ~scanf ( "%d%d%d" , &n , &m , &q ) ) solve () ; return 0 ;}
不同的姿势吧,还是推荐上面那种封装好的,比较方便
// whn6325689// Mr.Phoebe// http://blog.csdn.net/u013007900#include <algorithm>#include <iostream>#include <iomanip>#include <cstring>#include <climits>#include <complex>#include <fstream>#include <cassert>#include <cstdio>#include <bitset>#include <vector>#include <deque>#include <queue>#include <stack>#include <ctime>#include <set>#include <map>#include <cmath>#include <functional>#include <numeric>#pragma comment(linker, "/STACK:1024000000,1024000000")using namespace std;#define eps 1e-9#define PI acos(-1.0)#define INF 0x3f3f3f3f#define LLINF 1LL<<62#define speed std::ios::sync_with_stdio(false);typedef long long ll;typedef unsigned long long ull;typedef long double ld;typedef pair<ll, ll> pll;typedef complex<ld> point;typedef pair<int, int> pii;typedef pair<pii, int> piii;typedef vector<int> vi;#define CLR(x,y) memset(x,y,sizeof(x))#define CPY(x,y) memcpy(x,y,sizeof(x))#define clr(a,x,size) memset(a,x,sizeof(a[0])*(size))#define cpy(a,x,size) memcpy(a,x,sizeof(a[0])*(size))#define mp(x,y) make_pair(x,y)#define pb(x) push_back(x)#define lowbit(x) (x&(-x))#define MID(x,y) (x+((y-x)>>1))#define ls (idx<<1)#define rs (idx<<1|1)#define lson ls,l,mid#define rson rs,mid+1,r#define root 1,1,ntemplate<class T>inline bool read(T &n){ T x = 0, tmp = 1; char c = getchar(); while((c < '0' || c > '9') && c != '-' && c != EOF) c = getchar(); if(c == EOF) return false; if(c == '-') c = getchar(), tmp = -1; while(c >= '0' && c <= '9') x *= 10, x += (c - '0'),c = getchar(); n = x*tmp; return true;}template <class T>inline void write(T n){ if(n < 0) { putchar('-'); n = -n; } int len = 0,data[20]; while(n) { data[len++] = n%10; n /= 10; } if(!len) data[len++] = 0; while(len--) putchar(data[len]+48);}//-----------------------------------const int maxn = 300010;struct Query{ int a, b, i; bool operator < (const Query &rhs) const { return b < rhs.b; } void input(int ii = 0) { scanf("%d%d", &a, &b); if(a > b) swap(a, b); i = ii; }} que[maxn], e[maxn];int n, m, q, ans[maxn], block_tot;int ch[maxn][2], fa[maxn], rt[maxn], miv[maxn];int val[maxn], sum[maxn], rev[maxn];void ins(int x, int c){ for(int i = x; i <= n; i += i&(-i)) sum[i] += c;}int getsum(int x){ int ans = 0; for(int i = x; i; i -= i&(-i)) ans += sum[i]; return ans;}void update_rev(int r){ if(!r) return; swap(ch[r][0], ch[r][1]); rev[r] ^= 1;}void push_up(int x){ int lc = ch[x][0], rc = ch[x][1]; miv[x] = x; if(val[miv[lc]] < val[miv[x]]) miv[x] = miv[lc]; if(val[miv[rc]] < val[miv[x]]) miv[x] = miv[rc];}void push_down(int r){ if(rev[r]) { update_rev(ch[r][0]); update_rev(ch[r][1]); rev[r] = 0; }}bool judge(int u, int v){ while(fa[u]) u = fa[u]; while(fa[v]) v = fa[v]; return u == v;}void rotate(int x){ int y = fa[x], kind = ch[y][1]==x; ch[y][kind] = ch[x][!kind]; fa[ch[y][kind]] = y; fa[x] = fa[y]; fa[y] = x; ch[x][!kind] = y; if(rt[y]) rt[y] = 0, rt[x] = 1; else ch[fa[x]][ch[fa[x]][1]==y] = x; push_up(y);}void P(int r){ if(!rt[r]) P(fa[r]); push_down(r);}void splay(int x){ P(x); while(!rt[x]) { int f = fa[x], ff = fa[f]; if(rt[f]) rotate(x); else if((ch[ff][1]==f)==(ch[f][1]==x)) rotate(f), rotate(x); else rotate(x), rotate(x); } push_up(x);}void access(int x){ // return; for(int t = 0; x; t = x, x = fa[x]) { splay(x); rt[ch[x][1]] = 1; rt[ch[x][1]=t] = 0; push_up(x); }}void makeroot(int x){ access(x); splay(x); update_rev(x);}void cut(int x, int y){ makeroot(x); splay(y); fa[ch[y][0]] = fa[y]; fa[y] = 0; rt[ch[y][0]] = 1; ch[y][0] = 0; push_up(y);}void link(int x, int y){ makeroot(x); fa[x] = y;}int query(int x, int y){ makeroot(x); access(y); splay(y); return miv[y];}void gao(int u, int v, int i){ // printf("%d %d :: %d %d", u, v, fa[u], fa[v]); cout << endl; if(judge(u, v)) { int t = query(u, v); if(u == v || u <= val[t]) return; block_tot++; cut(t, e[t-n-1].a); cut(t, e[t-n-1].b); ins(val[t], -1); } block_tot--; val[n+i] = u; miv[n+i] = n+i; link(u, n+i); link(v, n+i); ins(u, 1); // for(int j = 1; j <= n+m; j++) // printf("%d ", fa[j]); // cout << "return" << i << ' ' << u << ' ' << v << ' ' << block_tot << endl;}int main(){ while(~scanf("%d%d%d", &n, &m, &q)) { for(int i = 0; i <= n; i++) val[i] = INF, sum[i] = 0; for(int i = 0; i <= n+m; i++) rev[i] = ch[i][0] = ch[i][1] = fa[i] = 0, rt[i] = 1; for(int i = 0; i < m; i++) e[i].input(); sort(e, e+m); for(int i = 0; i < q; i++) que[i].input(i); sort(que, que+q); block_tot = n; for(int i = 0, j = 0; i < q; i++) { int l = que[i].a, r = que[i].b; while(j < m && e[j].b <= r) { gao(e[j].a, e[j].b, j+1); j++; // printf("%d %d___\n", j, m); } ans[que[i].i] = block_tot + getsum(l-1); // printf("%d %d__%d\n", l-1, block_tot, que[i].i); } for(int i = 0; i < q; i++) printf("%d\n", ans[i]); } return 0;}
0 0
- 【HDU】5333 Undirected Graph【LCT+BIT】
- HDU 5333 Undirected Graph LCT+BIT
- HDU 5333 Undirected Graph【LCT+BIT】
- hdu 5333 Undirected Graph (LCT)
- [LCT 树状数组] HDU 5333 Undirected Graph
- HDU 5333 Undirected Graph
- HDU 5333 Undirected Graph 离线 LCT维护最大生成树+树状数组
- 【动态树】 HDOJ 5333 Undirected Graph
- HDU5333 Undirected Graph
- Undirected Graph BFS/DFS
- judge loop in undirected graph
- connect components in undirected graph
- Connected Component in Undirected Graph
- HDU 5333 [LCT][树状数组]
- implement a undirected graph use adjacent list
- Sicily 4378. connect components in undirected graph
- Detect cycle in an undirected graph
- Sicily 1002. connected components in undirected graph
- Android之UI
- 挑战程序设计竞赛里面的部分题目<用java写的>
- ios第三方库集成
- hdu1016-Prime Ring Problem(回溯法)
- PAT-中国大学MOOC-陈越、何钦铭-数据结构基础习题集 00-自测5. Shuffling Machine (20) (简单模拟)【二星级】
- HDU 5333 Undirected Graph【LCT+BIT】
- Java集合学习--HashMap、LinkedHashMap、TreeMap、HashTable
- 敏捷开发之Scrum基础
- 时间和日期函数
- 类与类之间的关系
- 基于RestEasy开发环境搭建
- Linux下使用inotify实现对文件的监控
- java自带线程池和队列详细讲解
- jdbc:oracle:thin:@192.168.3.98:1521:orcl(详解)