标签:
3 3 2 1 2 1 3 2 3 1 2 1 3
2 1
给定n个点m条边的无向图(有自环有重边) q个询问
对于某个询问 query : [l,r]
把所有的边 形如 {u,v} u,v其中一个或者两个都不在区间[l,r]上的 都删除,求此时残余图的连通分量数。
每个询问都是互相独立的,也就是每个询问都是从原图删除而来。
思路:
感觉很有道理的样子,写了一发,卡常数卡死人了。。
#pragma comment(linker, "/STACK:1024000000")
#include <iostream>
#include <fstream>
#include <string>
#include <time.h>
#include <vector>
#include <map>
#include <queue>
#include <algorithm>
#include <stack>
#include <cstring>
#include <cmath>
#include <set>
#include <vector>
using namespace std;
template <class T>
inline bool rd(T &ret) {
char c; int sgn;
if (c = getchar(), c == EOF) return 0;
while (c != '-' && (c<'0' || c>'9')) c = getchar();
sgn = (c == '-') ? -1 : 1;
ret = (c == '-') ? 0 : (c - '0');
while (c = getchar(), c >= '0'&&c <= '9') ret = ret * 10 + (c - '0');
ret *= sgn;
return 1;
}
template <class T>
inline void pt(T x) {
if (x < 0) {
putchar('-');
x = -x;
}
if (x > 9) pt(x / 10);
putchar(x % 10 + '0');
}
typedef long long ll;
typedef pair<int, int> pii;
const int N = 1e5 + 100;
const int inf = 10000000;
struct BIT {
int c[N], maxn;
void init(int n) {
maxn = n;
memset(c, 0, (10 + n) *sizeof(int));
}
int lowbit(int x) { return x&-x; }
int sum(int x) {
int ans = 0;
while (x)ans += c[x], x -= lowbit(x);
return ans;
}
int query(int l, int r) {
return sum(r) - sum(l - 1);
}
void change(int x, int val) {
while (x<=maxn)c[x] += val, x += lowbit(x);
}
}bit;
struct Node *null;
struct Node {
Node *fa, *ch[2];
int val;
int mi, min_id, id;
bool rev;
inline void put() {
printf("%d: fa:%d [%d,%d] val:%d ma:%d,%d rev:%d\n", id, fa->id, ch[0]->id, ch[1]->id, val, mi, min_id, rev);
}
inline void clear(int _id) {
fa = ch[0] = ch[1] = null;
rev = 0;
id = _id;
mi = inf;
min_id = 0;
val = 0;
}
inline void push_up() {
if (this == null)return;
if (val) {
mi = min(id, min(ch[0]->mi, ch[1]->mi));
if (id <= min(ch[0]->mi, ch[1]->mi)) min_id = id;
else if (ch[0]->mi < min(ch[1]->mi, id ))min_id = ch[0]->min_id;
else min_id = ch[1]->min_id;
}
else
{
mi = min(ch[0]->mi, ch[1]->mi);
if (ch[0]->mi < ch[1]->mi)min_id = ch[0]->min_id;
else min_id = ch[1]->min_id;
}
}
inline void push_down() {
if (this == null)return;
if (rev) {
ch[0]->flip();
ch[1]->flip();
rev = 0;
}
}
inline void setc(Node *p, int d) {
ch[d] = p;
p->fa = this;
}
inline bool d() {
return fa->ch[1] == this;
}
inline bool isroot() {
return fa == null || fa->ch[0] != this && fa->ch[1] != this;
}
inline void flip() {
if (this == null)return;
swap(ch[0], ch[1]);
rev ^= 1;
}
inline void go() {//从链头开始更新到this
if (!isroot())fa->go();
push_down();
}
inline void rot() {
Node *f = fa, *ff = fa->fa;
int c = d(), cc = fa->d();
f->setc(ch[!c], c);
this->setc(f, !c);
if (ff->ch[cc] == f)ff->setc(this, cc);
else this->fa = ff;
f->push_up();
}
inline Node*splay() {
go();
while (!isroot()) {
if (!fa->isroot())
d() == fa->d() ? fa->rot() : rot();
rot();
}
push_up();
return this;
}
inline Node* access() {//access后this就是到根的一条splay,并且this已经是这个splay的根了
for (Node *p = this, *q = null; p != null; q = p, p = p->fa) {
p->splay()->setc(q, 1);
p->push_up();
}
return splay();
}
inline Node* find_root() {
Node *x;
for (x = access(); x->push_down(), x->ch[0] != null; x = x->ch[0]);
return x;
}
void make_root() {
access()->flip();
}
void cut() {//把这个点的子树脱离出去
access();
ch[0]->fa = null;
ch[0] = null;
push_up();
}
void cut(Node *x) {
if (this == x || find_root() != x->find_root())return;
else {
x->make_root();
cut();
}
}
void link(Node *x) {
if (find_root() == x->find_root())return;
else {
make_root(); fa = x;
}
}
};
Node pool[N], *tail;
Node *node[N];
void init(int n) {
tail = pool;
null = tail++;
null->clear(0);
for (int i = 1; i <= n; i++) {
node[i] = tail++;
node[i]->clear(i);
}
}
void debug(Node *x) {
if (x == null)return;
x->put();
debug(x->ch[0]);
debug(x->ch[1]);
}
int n, m, q;
struct BST {
int f[N];
void init(int n) { for (int i = 1; i <= n; i++)f[i] = i; }
int find(int x) { return x == f[x] ? x : f[x] = find(f[x]); }
void Union(int u, int v) {
u = find(u); v = find(v);
if (u == v)return;
if (u > v)swap(u, v);
f[u] = v;
}
}cha;
void insert(int x, int y) {
// puts("**==="); for (int i = 1; i <= max(x, y); i++)debug(node[i]), puts("");puts("");
if (cha.find(x) == cha.find(y)) {
node[y]->access();
// puts("**"); for (int i = 1; i <= max(x, y); i++)debug(node[i]), puts("");puts("");
int id = node[y]->min_id;
if (y <= id)return;
// printf("change id:%d\n", id);
bit.change(id, -1);
node[id]->val--;
node[id]->cut(node[x]);
}
else cha.Union(x, y);
// puts("---------");for (int i = 1; i <= x; i++)debug(node[i]), puts("");puts("");
bit.change(y, 1);
node[y]->make_root();
node[y]->val++;
node[y]->push_up();
node[y]->fa = node[x];
// puts("@@@@@@");for (int i = 1; i <= x; i++)debug(node[i]), puts("");puts("");
}
int ans[N];
struct {
struct Edge {
int to, nex, id;
}edge[N << 1];
int head[N], edgenum;
void init(int n) {
memset(head, -1, (10 + n) *sizeof(int));
edgenum = 0;
}
void add(int u, int v, int id = 0) {
Edge E = { v, head[u], id};
edge[edgenum] = E;
head[u] = edgenum++;
}
}E, Q;
int main() {
while (~scanf("%d%d%d", &n,&m,&q)) {
E.init(n); Q.init(n); cha.init(n);
for (int i = 0, u, v;i < m; i++)
{
rd(u), rd(v);
if (u == v) {i--, m--;continue;}
if (u < v)E.add(v, u);else E.add(u, v);
}
for (int i = 0, u, v;i < q; i++) {
rd(u); rd(v);
Q.add(v, u, i);
}
bit.init(n);
init(n);
for (int i = 1; i <= n; i++)
{
for (int j = E.head[i]; ~j; j = E.edge[j].nex)
insert(i, E.edge[j].to);
for (int j = Q.head[i]; ~j; j = Q.edge[j].nex)
ans[Q.edge[j].id] = n - bit.query(Q.edge[j].to, i);
}
for (int i = 0; i < q; i++) pt(ans[i]), puts("");
}
return 0;
}
/*
7 9 1
1 2
1 3
1 5
1 6
4 7
4 6
2 7
6 2
4 3
2 7
ans:3
*/
版权声明:本文为博主原创文章,未经博主允许不得转载。
HDU 5333 Undirected Graph LCT+BIT
标签:
原文地址:http://blog.csdn.net/qq574857122/article/details/47214353