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. 怎样将Oracle数据库设置为归档模式及非归档模式

    怎样将Oracle数据库设置为归档模式及非归档模式 1.Oracle日志分类 分三大类: Alert log files--警报日志,Trace files--跟踪日志(用户和进程)和 redo lo ...

  2. dSYM文件

    来到新公司后,前段时间就一直在忙,前不久 项目 终于成功发布上线了,最近就在给项目做优化,并排除一些线上软件的 bug,因为项目中使用了友盟统计,所以在友盟给出的错误信息统计中能比较方便的找出客户端异 ...

  3. 洛谷 P2717 寒假作业

    https://www.luogu.org/problemnew/show/P2717 $n \le 1004枚举区间,挨个计算,判断,时间复杂度$O(n^3)$. $n \le 5000$,预处理出 ...

  4. Docker自学纪实(一)Docker介绍

    先简单了解一下,做个记录,以便不时之需. Docker简介:Docker 是一个开源的应用容器引擎,基于 Go 语言 并遵从Apache2.0协议开源. Docker 可以让开发者打包他们的应用以及依 ...

  5. NodeJS基础入门-Event

    大多数Node.js核心API都采用惯用的异步事件驱动架构,其中某些类型的对象(触发器)会周期性地触发命名事件来调用函数对象(监听器). 例如,net.Server对象会在每次有新连接时触发事件;fs ...

  6. LeetCode之Weekly Contest 91

    第一题:柠檬水找零 问题: 在柠檬水摊上,每一杯柠檬水的售价为 5 美元. 顾客排队购买你的产品,(按账单 bills 支付的顺序)一次购买一杯. 每位顾客只买一杯柠檬水,然后向你付 5 美元.10  ...

  7. 购物车小程序(while循环,列表)

    while True: salary = input("please input your salary:") if salary.isdigit(): salary=int (s ...

  8. 18/07/2017 R matrix

    矩阵:二维数组,元素拥有相同模式(数值型,字符型或者逻辑型) mymatrix <- matrix (vector, nrow_num_of_rows, ncol_num_of_columns, ...

  9. apicloud入门学习笔记1:简单介绍

    官网地址:https://www.apicloud.com/ 新手开发指南:https://docs.apicloud.com/APICloud/junior-develop-guide 开发语言:H ...

  10. ACM 广度优化搜索算法总结

    广度优化搜索算法的本质:要求每个状态不能重复,这就需要我们:第一次先走一步可以到达的状态,如果还没有找到答案,就需要我们走到两步可以到达的状态.依次下去 核心算法:队列 基本步骤:          ...