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. Java中List集合排序的方法 比较器的使用 根据学生对象数学 语文 英语成绩总和进行sort排序

    package com.swift; import java.util.ArrayList; import java.util.Collections; import java.util.Compar ...

  2. 使用mfc CHtmlView内存泄露解决方法

    第一步,谷歌有文章说CHtmlView部分api使用BSTR没释放: 解决方法是重写一下接口: CString GetFullName() const; CString GetFullName() c ...

  3. 用promise封装ajax

    首先贴代码 var ajaxOptions = { url: 'url', method: 'GET', async: true, data: null, dataType: 'text', } fu ...

  4. 基于idea创建Tomcat远程调试

    编辑完catalina文件后重启tomcat

  5. LeetCode(23)Merge k Sorted Lists

    题目 Merge k sorted linked lists and return it as one sorted list. Analyze and describe its complexity ...

  6. Java技术——多态的实现原理

    .方法表与方法调用 如有类定义 Person, Girl, Boy class Person { public String toString(){ return "I'm a person ...

  7. UVa 11149 Power of Matrix 矩阵快速幂

    题意: 给出一个\(n \times n\)的矩阵\(A\),求\(A+A^2+A^3+ \cdots + A^k\). 分析: 这题是有\(k=0\)的情况,我们一开始先特判一下,直接输出单位矩阵\ ...

  8. HDU 3376 费用流 Matrix Again

    题意: 给出一个n × n的矩阵,每个格子中有一个数字代表权值,找出从左上角出发到右下角的两条不相交的路径(起点和终点除外),使得两条路径权值之和最大. 分析: 如果n比较小的话是可以DP的,但是现在 ...

  9. python面试题解析(数据库和缓存)

    1.     答: 关系型数据库:Mysql,Oracel,Microsoft SQL Server 非关系型数据库:MongoDB,memcache,Redis. 2.     答:     MyI ...

  10. Python学习-day10 进程

    学习完线程,学习进程 进程和线程的语法有很多一样的地方,不过在操作系统中的差别确实很大. 模块是threading 和 multiprocessing 多进程multiprocessing multi ...