HDU 6218 Bridge

Problem :

给一个2×n的矩阵,一开始矩阵所有相邻点之间有一条边。有其、个询问,每次给出两个相邻的点的坐标,将其中的边删除或者添加,问如此操作之后整张图的割边数量。

, q<=2*10^5, 图始终保证联通。

Solution :

首先可以发现不能成为割边的边,一定被某个环所包含。因此只要维护每个环的大小即可。

若某条横边在两行中均出现了两次,才有可能构成环。用set来维护所有连续的横边。再用线段树来维护所有竖边的位置。

计算一条连续的横边产生的不能成为割边的数量,统计其中最左和最右的竖边以及竖边的数量就行了。

#include <bits/stdc++.h>

using namespace std;

const int N = 2e5 + 8;
const int INF = 1e9 + 7; #define endl "\n"
#define y1 qqq
struct node
{
int l, r;
node(){}
node(int l, int r):l(l),r(r){}
bool operator < (const node &b) const
{
return l < b.l;
}
};
multiset <node> S;
int n, q, mtot, num;
int cnt[N];
class Segment_Tree
{
public:
int tagmin[N << 2], tagmax[N << 2], tagsum[N << 2];
void pushup(int rt)
{
tagmin[rt] = min(tagmin[rt << 1], tagmin[rt << 1 | 1]);
tagmax[rt] = max(tagmax[rt << 1], tagmax[rt << 1 | 1]);
tagsum[rt] = tagsum[rt << 1] + tagsum[rt << 1 | 1];
}
void build(int l, int r, int rt)
{
tagmin[rt] = INF; tagmax[rt] = 0; tagsum[rt] = 0;
if (l == r)
{
tagmin[rt] = tagmax[rt] = l;
tagsum[rt] = 1;
return;
}
int m = l + r >> 1;
build(l, m, rt << 1);
build(m + 1, r, rt << 1 | 1);
pushup(rt);
}
void update(int x, int op, int l, int r, int rt)
{
if (l == r)
{
if (op == 1)
{
tagmin[rt] = tagmax[rt] = l; tagsum[rt] = 1;
}
else
{
tagmin[rt] = INF; tagmax[rt] = 0; tagsum[rt] = 0;
}
return;
}
int m = l + r >> 1;
if (x <= m) update(x, op, l, m, rt << 1);
else update(x, op, m + 1, r, rt << 1 | 1);
pushup(rt);
}
void querymax(int L, int R, int l, int r, int rt, int &ans)
{
if (L <= l && r <= R)
{
ans = max(ans, tagmax[rt]);
return;
}
int m = l + r >> 1;
if (L <= m) querymax(L, R, l, m, rt << 1, ans);
if (m < R) querymax(L, R, m + 1, r, rt << 1 | 1, ans);
}
void querymin(int L, int R, int l, int r, int rt, int &ans)
{
if (L <= l && r <= R)
{
ans = min(ans, tagmin[rt]);
return;
}
int m = l + r >> 1;
if (L <= m) querymin(L, R, l, m, rt << 1, ans);
if (m < R) querymin(L, R, m + 1, r, rt << 1 | 1, ans);
}
void querysum(int L, int R, int l, int r, int rt, int &ans)
{
if (L <= l && r <= R)
{
ans += tagsum[rt];
return;
}
int m = l + r >> 1;
if (L <= m) querysum(L, R, l, m, rt << 1, ans);
if (m < R) querysum(L, R, m + 1, r, rt << 1 | 1, ans);
}
}T;
int calc(int l, int r)
{
int L = INF, R = -INF, sum = 0;
T.querymin(l, r, 1, n, 1, L);
T.querymax(l, r, 1, n, 1, R);
T.querysum(l, r, 1, n, 1, sum);
if (sum <= 1) return 0;
return (R - L) * 2 + sum;
}
void init()
{
cin >> n >> q;
T.build(1, n, 1);
S.clear();
for (int i = 1; i <= n; ++i) cnt[i] = 2;
S.insert(node(1, n));
S.insert(node(-1, -1));
S.insert(node(n + 2, n + 2));
mtot = 3 * n - 2;
num = calc(1, n);
}
void work_row_add(int x)
{
auto l = S.upper_bound(node(x, x + 1)); l--;
auto r = S.lower_bound(node(x, x + 1));
cnt[x]++; mtot++;
if (cnt[x] == 1)
{
cout << mtot - num << endl;
return;
}
if (l->r == x && r->l == x + 1)
{
num -= calc(l->l, l->r);
num -= calc(r->l, r->r);
num += calc(l->l, r->r);
S.insert(node(l->l, r->r));
S.erase(l);
S.erase(r);
}
else if (l->r == x && r->l != x + 1)
{
num -= calc(l->l, l->r);
num += calc(l->l, x + 1);
S.insert(node(l->l, x + 1));
S.erase(l);
}
else if (l->r != x && r->l == x + 1)
{
num -= calc(r->l, r->r);
num += calc(x, r->r);
S.insert(node(x, r->r));
S.erase(r);
}
else if (l->r != x && r->l != x + 1)
{
num += calc(x, x + 1);
S.insert(node(x, x + 1));
}
}
void work_row_del(int x)
{
auto p = S.upper_bound(node(x, x + 1)); p--;
cnt[x]--; mtot--;
if (cnt[x] == 0) return;
if (p->l == x && p->r == x + 1)
{
num -= calc(x, x + 1);
S.erase(p);
}
else if (p->l == x && p->r != x + 1)
{
num += calc(x+1,p->r);
num -= calc(p->l,p->r);
S.insert(node(x+1,p->r));
S.erase(p);
}
else if (p->l != x && p->r == x + 1)
{
num += calc(p->l,x);
num -= calc(p->l,p->r);
S.insert(node(p->l,x));
S.erase(p);
}
else if (p->l != x && p->r != x + 1)
{
num -= calc(p->l, p->r);
num += calc(p->l, x);
num += calc(x+1, p->r);
S.insert(node(p->l, x));
S.insert(node(x+1, p->r));
S.erase(p);
}
}
void work_col_add(int x)
{
auto p = S.upper_bound(node(x, x)); p--;
mtot++;
if (p->r >= x)
{
num -= calc(p->l, p->r);
T.update(x, 1, 1, n, 1);
num += calc(p->l, p->r);
}
else
{
T.update(x, 1, 1, n, 1);
}
}
void work_col_del(int x)
{
auto p = S.upper_bound(node(x, x)); p--;
mtot--;
if (p->r >= x)
{
num -= calc(p->l, p->r);
T.update(x, -1, 1, n, 1);
num += calc(p->l, p->r);
}
else
{
T.update(x, -1, 1, n, 1);
}
}
void solve()
{
for (; q; --q)
{
int op, x1, y1, x2, y2;
cin >> op >> x1 >> y1 >> x2 >> y2; if (y1 > y2) swap(y1, y2);
if (op == 1)
if (x1 == x2) work_row_add(y1);
else work_col_add(y1);
else
if (x1 == x2) work_row_del(y1);
else work_col_del(y1);
cout << mtot - num << endl;
}
}
int main()
{
cin.sync_with_stdio(0);
int T; cin >> T;
for (int cas = 1; cas <= T; ++cas)
{
init();
solve();
}
}

HDU 6218 (线段树+set)的更多相关文章

  1. hdu 5877 线段树(2016 ACM/ICPC Asia Regional Dalian Online)

    Weak Pair Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others)Total ...

  2. hdu 3974 线段树 将树弄到区间上

    Assign the task Time Limit: 15000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) ...

  3. hdu 3436 线段树 一顿操作

    Queue-jumpers Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) To ...

  4. hdu 3397 线段树双标记

    Sequence operation Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Othe ...

  5. hdu 4578 线段树(标记处理)

    Transformation Time Limit: 15000/8000 MS (Java/Others)    Memory Limit: 65535/65536 K (Java/Others) ...

  6. hdu 4533 线段树(问题转化+)

    威威猫系列故事——晒被子 Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others) Tot ...

  7. hdu 2871 线段树(各种操作)

    Memory Control Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) T ...

  8. hdu 4052 线段树扫描线、奇特处理

    Adding New Machine Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Othe ...

  9. hdu 1542 线段树扫描(面积)

    Atlantis Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Su ...

随机推荐

  1. Object-C知识点 (五) NSObject的继承关系

    这篇文章主要介绍常用的继承自NSObject的类,方便朋友们查看和面试前查看使用!!! 结构图: 更多内容--> 博客导航 每周一篇哟!!! 有任何关于iOS开发的问题!欢迎下方留言!!!或者邮 ...

  2. 【kmp】bzoj3620: 似乎在梦中见过的样子

    考察kmp理解题 Description “Madoka,不要相信 QB!”伴随着 Homura 的失望地喊叫,Madoka 与 QB 签订了契约. 这是 Modoka 的一个噩梦,也同时是上个轮回中 ...

  3. Python基础(五)——闭包与lambda的结合

    (1)变量的域 要了解闭包需要先了解变量的域,也就是变量在哪一段“上下文”是有效的(类似局部变量和全局变量的区别),举一个很简单的例子.(例子不重要,就是涉及闭包就要时刻关注这个域) def test ...

  4. python中字典的‘增、删、改、查’

    python 字典的'增.删.改.查' 用 ipython 运行情况如下: #新建字典 In [1]: infos = {'name':'dongge','age':18} In [2]: infos ...

  5. python3.7 文件操作

    #!/usr/bin/env python __author__ = "lrtao2010" #python3.7 文件操作 # r 只读,默认打开方式,当文件不存在时会报错 # ...

  6. spring关于@Autowired和@Qualifier的使用

    // package com.jhc.model; import org.springframework.stereotype.Component; @Component public interfa ...

  7. BNU 3692 I18n 模拟

    题意: 在一篇文章中,单词可以缩写.例如单词Internationalization可以缩写为I18n,缩写的两端是原单词的首尾字母,中间的数字是被省略的字母的个数. 现在给你一篇缩写的文章,输出展开 ...

  8. mongodb v2.4.9 快速操作记录

    参考链接:http://www.runoob.com/mongodb/mongodb-tutorial.html oschina链接:https://gitee.com/dhclly/icedog.s ...

  9. SpringMVC 页面传递参数到controller的五种方式

    一共是五种传参方式: 一:直接将请求参数名作为Controller中方法的形参 public  String login (String username,String password)   : 解 ...

  10. python3--类与继承和组合

    类和继承:“是一个”关系 我们已经深入探索了继承的机制,这里举个例子来说明它是如何用于模拟真实世界的关系的.从程序员的角度来看,继承是由属性点号运算启动的,由此触发实例.类以及任何超类中的变最名搜索. ...