HDU 6218 (线段树+set)
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)的更多相关文章
- 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 ...
- hdu 3974 线段树 将树弄到区间上
Assign the task Time Limit: 15000/5000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) ...
- hdu 3436 线段树 一顿操作
Queue-jumpers Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) To ...
- hdu 3397 线段树双标记
Sequence operation Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Othe ...
- hdu 4578 线段树(标记处理)
Transformation Time Limit: 15000/8000 MS (Java/Others) Memory Limit: 65535/65536 K (Java/Others) ...
- hdu 4533 线段树(问题转化+)
威威猫系列故事——晒被子 Time Limit: 3000/1000 MS (Java/Others) Memory Limit: 65535/32768 K (Java/Others) Tot ...
- hdu 2871 线段树(各种操作)
Memory Control Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) T ...
- hdu 4052 线段树扫描线、奇特处理
Adding New Machine Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Othe ...
- hdu 1542 线段树扫描(面积)
Atlantis Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Su ...
随机推荐
- javascript 完整知识点整理
by 蔡舒啸 目录 一 5种基本类型 typeof 关键字 三种强制类型转换 日期 二 if语句for语句whiledo-whileswitch-case 比较运算符 逻辑运算符 if for语句 w ...
- C语言中声明和定义详解(待看。。
变量声明和变量定义 变量定义:用于为变量分配存储空间,还可为变量指定初始值.程序中,变量有且仅有一个定义. 变量声明:用于向程序表明变量的类型和名字. 定义也是声明,extern声明不是定义 定义也是 ...
- [bzoj]1003: [ZJOI2006]物流运输
Description 物流公司要把一批货物从码头A运到码头B.由于货物量比较大,需要n天才能运完.货物运输过程中一般要转停好几个码头.物流公司通常会设计一条固定的运输路线,以便对整个运输过程实施严格 ...
- POJ-1961-Period(ZOJ-2177)
这题是最短循环节,然后我们尝试小于字符串长度的所有长度,如果符合,我们就输出. 如果它等于0,说明它不循环,因为之前并没有重复的,如果i%(i-next[i])==0说明它是循环的,然后除一下得到周期 ...
- 【MySql】Mysql ERROR 1067: Invalid default value for ‘date’ 解决
在给一个表添加字段的时候,忽然发现会报一个date类型的字段的默认值错误,郁闷~ 经过排查,原来是MySQL的配置问题,在wamp下,MySQL 5.7里是没有设置 SQL_MODE 的. 1.my. ...
- 如何用纯 CSS 创作一组昂首阔步的圆点
效果预览 在线演示 按下右侧的"点击预览"按钮可以在当前页面预览,点击链接可以全屏预览. https://codepen.io/comehope/pen/ejrMKe 可交互视频 ...
- angular4使用代理
1. 在angular-cli项目根目录下创建proxy.config.json { "/api/v1": { "target": "http://1 ...
- 阿里云全国快递物流查询api接口
口地址: https://market.aliyun.com/products/56928004/cmapi021863.html?spm=5176.730005.productlist.d_cmap ...
- Jack Straws POJ - 1127 (几何计算)
Jack Straws Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 5428 Accepted: 2461 Descr ...
- HDU 3072 SCC Intelligence System
给出一个带权有向图,要使整个图连通.SCC中的点之间花费为0,所以就先缩点,然后缩点后两点之间的权值为最小边的权值,把这些权值累加起来就是答案. #include <iostream> # ...