矩阵面积并 模板
扫描线思想
使用离散化的数字,在线段树上创建了长度不同的线段
维护最小值和最小值数量,最小值如果是0的话,就说明需要减去这部分
一定要注意标记下放和向上更新!
#include<iostream>
#include<algorithm>
#include<string>
#include<vector>
#include<cmath>
#include<map>
#include<set>
#include<queue>
#include<stdio.h>
#include<stack>
#include<list>
#include<tuple>
#include<ctime>
#include<cstdlib>
#include<bit>
#include<sys/timeb.h>
using namespace std;
#define ffp(x,y,z) for(ll (x) = (y);(x)<=(z);(x++))
#define ffs(x,y,z) for(ll (x) = (y);(x)>=(z);(x--))
#define pii pair<ll ,ll>
#define ll long long int
#define q_ (qd())
const double ex = 1e-7;
const int iINF = 0x3f3f3f3f;
const ll lINF = 0x3f3f3f3f3f3f3f3f;
const ll MOD = 998244353;
long long int qd() {
long long w = 1, c, ret;
while ((c = getchar()) > '9' || c < '0')
w = (c == '-' ? -1 : 1); ret = c - '0';
while ((c = getchar()) >= '0' && c <= '9')
ret = ret * 10 + c - '0';
return ret * w;
}
int stime()
{
timeb ti;
static bool f = 1;
ftime(&ti);
while (1)
{
if (f) { srand(ti.millitm * 117); f = 0; }
int temp = rand();
if (temp) { return temp > 0 ? temp : -temp; }
}
}
ll gcd(ll a, ll b)
{
if (a == 0)return b;
return a % b == 0 ? b : gcd(b, a % b);
}
ll qs(ll a, ll b)
{
a %= MOD;
ll bei = a;
a = 1;
while (b)
{
if (b & 1) { a = a * bei % MOD; }
bei = bei * bei % MOD;
b >>= 1;
}
return a;
}
ll inv(ll a)
{
return qs(a, MOD - 2);
}
static ll Max(ll a1 = -lINF, ll a2 = -lINF, ll a3 = -lINF, ll a4 = -lINF, ll a5 = -lINF)
{
return max(max(max(max(a1, a2), a3), a4), a5);
}
static ll Min(ll a1 = lINF, ll a2 = lINF, ll a3 = lINF, ll a4 = lINF, ll a5 = lINF)
{
return min(min(min(min(a1, a2), a3), a4), a5);
}
struct line
{
ll minv;//最小值的值是?
ll sum;//最小值的个数是?
ll lon;//长度
ll lz;
};//一段线段长
line operator+(line a, line b)
{
if (a.minv == b.minv)
{
return { a.minv,a.sum + b.sum,a.lon + b.lon };
}
else if (a.minv < b.minv)
{
return { a.minv,a.sum,a.lon + b.lon };
}
else if (a.minv > b.minv)
{
return { b.minv,b.sum,a.lon + b.lon };
}
}
int main()
{//矩形面积并,离散化数据
//需要特殊的线段树
//线段树要维护的值是:最小值,以及最小值的个数
// 有1e5个点,那就线段有1e5个
ll n = q_;
vector<tuple<ll, ll, ll, ll>>evt;
vector<ll>vy;//离散化的y坐标
vector<line>tr(200200 << 3);
ffp(i, 1, n)
{
//上下扫的扫描线
int x1 = q_;
int y1 = q_;
int x2 = q_;
int y2 = q_;
vy.push_back(y1);
vy.push_back(y2);
//以x坐标进行排序 x为行号
evt.push_back({ x1,1,y1,y2 });
evt.push_back({ x2,-1,y1,y2 });
}
sort(evt.begin(), evt.end());
sort(vy.begin(), vy.end());
vy.erase(unique(vy.begin(), vy.end()),vy.end());//离散化的去重
auto pushdown = [&](int rt)->void
{
// tr[rt].minv += tr[rt].lz;
tr[rt * 2].lz += tr[rt].lz;
tr[rt * 2].minv += tr[rt].lz;
tr[rt * 2 + 1].lz += tr[rt].lz;
tr[rt * 2 + 1].minv += tr[rt].lz;
tr[rt].lz = 0;
};
auto updata = [&](int rt)->void
{
};
auto bud = [&](auto&& bud, int rt, int l, int r)->void
{
if (l == r)
{
tr[rt].minv = 0;
tr[rt].sum = vy[r] - vy[r - 1];
tr[rt].lon = vy[r] - vy[r - 1];
return;
}//一段的长度是不同的
bud(bud, rt * 2, l, (l + r) >> 1);
bud(bud, rt * 2 + 1, ((l + r) >> 1) + 1, r);
tr[rt] = tr[rt * 2] + tr[rt * 2 + 1];
};
auto push = [&](auto&& push, int rt, int l, int r, int y1, int y2,int va)->void
{
if (y1 <= l && r <= y2)
{//更新当前的值
tr[rt * 2].lz += va;
tr[rt * 2 + 1].lz += va;
tr[rt * 2].minv += va;
tr[rt * 2 + 1].minv += va;
tr[rt].minv += va;
return;
}
if (tr[rt].lz)pushdown(rt);
int med = (l + r) >> 1;
if (y1 <= med)push(push, rt * 2, l, med, y1, y2, va);
if (y2 > med)push(push, rt * 2 + 1, med + 1, r, y1, y2, va);
tr[rt] = tr[rt * 2] + tr[rt * 2 + 1];
//这里需要个向上更新
// updata(rt);
};
ll m = vy.size() - 1;
bud(bud,1, 1, m);//只有m段
ll prex = 0;//上一个的x所在的地方
ll ans = 0;
ll all = tr[1].sum;
for (auto& e : evt)
{
auto [p, va, y1, y2] = e;
ll minv = tr[1].minv;
ll cnt = all;
//每次先计算答案 然后再把一条线段放到线段树里,或者把一条线段拿走
if (minv == 0)cnt = all -tr[1].sum;
ans += (p - prex) * cnt;
//线段树push
int x1 = lower_bound(vy.begin(), vy.end(), y1) - vy.begin() + 1;
int x2 = lower_bound(vy.begin(), vy.end(), y2) - vy.begin();
push(push, 1, 1, m, x1, x2, va);
prex = p;
}
cout << ans << endl;
return 0;
}
/*
⡀⠎⠀⠀⠀⠀⠀⠀⠀⣸⣿⣿⣿⣿⣄⠃⠈⣶⡛⠿⠭⣉⠛⠿⡿⠛⠉⣀⣠⣤⣭⡏⠴⢀⣴⣿⣿⣿⣿⣿⣿⠀⠀⠀⠀⠀⠀⠀⠙⣿⣿
⠀⠀⠀⠀⠀⠀⠀⠀⣿⣿⣿⣿⣿⣿⣷⣱⣬⠛⠉⠀⠀⢠⠀⠀⠀⢀⣀⠀⠉⠿⣿⣾⣿⣿⣿⣿⣿⣿⣿⣿⠀⠀⠀⠀⠀⠀⠀⠀⠈⡿
⠀⠀⠀⠀⠀⠀⠀⢀⢿⣿⣿⣿⣿⣿⣿⠋⠀⠀⠀⠀⠀⡏⠀⠀⠀⠀⠈⠳⠀⠀⠀⠻⣿⣿⣿⣿⣿⣿⠋⠀⣇⠀⠀⠀⠀⠀⠀⠀⠀⠈
⠀⠀⠀⠀⠀⠀⠀⣸⠀⣿⣿⣿⣿⠟⠀⠀⠀⠂⠀⠀⢠⠀⠀⠀⠀⠀⠀⠀⠈⡀⠀⠀⠀⠻⣿⣿⣿⣿⣷⡀⠘
⠀⠀⠀⠀⠀⠀⠀⣧⣿⣿⣿⣿⠋⠀⠀⠀⠀⠀⠀⠀⢸⠀⠀⠀⠀⠀⠀⠀⠀⠈⠀⠀⠀⠀⠙⣿⣿⣿⣿⣿⣄⣧
⠀⠀⠀⠀⠀⠀⣸⣿⣿⣿⣿⠁⠀⠀⠀⠀⠀⠀⠀⠀⣾⠀⠀⠀⠀⠀⠀⠀⠀⠀⢧⠀⠀⠀⠀⠈⢿⣿⣿⣿⣿⣿⣆
⠀⠀⠀⠀⠀⢀⣿⣿⣿⣿⠇⠀⠀⠀⠀⠀⠀⠀⠀⠀⢹⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠀⠀⠀⠀⠀⢂⠻⣿⣿⣿⣿⣿⣄
⠀⠀⠀⠀⠀⣿⣿⣿⣿⣹⠀⠀⠀⠀⠀⢸⠀⠀⠀⠀⠸⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣇⠀⠀⠀⠀⠀⡄⠈⢿⣿⣿⣿⣿⣆
⠀⠀⠀⠀⣿⣿⣿⣿⠁⡇⠀⠀⠀⠀⠀⢸⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣿⠀⠀⠀⠀⠐⠸⠀⠀⠻⣿⣿⣿⣆⢦
⠀⠀⢠⣿⣿⣿⣿⠃⠀⠀⠀⠀⠀⠀⠀⣼⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡏⣧⠀⠀⠀⠀⠐⣇⠀⠀⠙⣿⣿⣿⡄⠙⣄
⠀⣴⣿⣿⣿⣿⠏⠀⢸⠀⠀⠀⠀⠀⠀⡿⢿⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣃⣈⣦⠀⠀⠀⠀⢹⠀⠀⠀⠸⣿⣿⣿⠀⠀⠳⣀
⠋⣸⣿⣿⣿⡟⠀⠀⠀⡆⠀⠀⠀⠀⠀⡏⠙⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢰⠀⢠⠀⠀⠀⢧⠀⠀⠀⠀⡇⠀⠀⠀⠘⣿⣿⣷⠀⠀⠘
⠀⣿⣿⣿⢩⠀⠀⠀⠀⣿⠀⠀⠀⠀⠀⣀⠀⢱⠀⡀⠀⠀⠀⠀⠀⠀⠀⠀⣿⠀⠂⢀⣴⣶⣿⣿⡀⠀⠀⢻⠀⠀⠀⠀⠹⣿⣿⡄
⢸⣿⣿⠃⠈⠀⠀⢸⠀⣿⣆⠀⠀⠀⠀⣿⣿⣿⠷⠘⡀⠀⠀⠀⠀⠀⠀⢠⢹⡀⠈⡿⠻⣿⣛⢿⣿⣷⡀⠈⠀⠀⠀⠀⠀⢻⣿⣿
⣿⣿⣿⠀⠀⠀⠀⢸⠀⡇⣼⣄⠀⠀⠀⢻⣿⡄⠑⠑⣿⡀⠀⠀⠀⢀⠀⠂⠇⠀⠀⠖⠛⢿⣿⣿⣌⢿⣿⣿⡆⠀⠀⠀⠀⠀⣿⣿⡀
⣿⣿⡇⠀⠀⠀⠀⢸⠀⣾⣿⣿⡷⠿⣷⣤⣿⣿⡄⠀⠀⠀⠑⠤⡀⠀⠃⠀⠀⠀⠀⣿⣶⣿⣿⣿⣿⣆⠙⣿⣧⠀⠀⠀⠀⠀⣿⣿⡇
⣿⣿⠁⠀⠀⠀⠀⠘⣾⣿⣿⠁⣴⣿⣿⣿⣿⣿⣇⠀⠀⠀⠀⠀⠀⠈⠀⠀⠀⠀⠀⠸⡏⠙⣿⠉⠻⣿⠀⠀⣿⠀⠀⠀⣄⠀⣿⢸⣷
⣿⣿⡇⠀⠀⠀⠀⠀⣿⣿⠁⠀⣿⣿⠋⣿⠏⠙⠇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢹⠀⢀⢻⠀⠀⢀⡟⢀⣿⣸⢃⠟
⣿⣿⣿⠀⡄⠀⠀⠀⠘⠻⡄⠀⢹⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡘⠀⢀⣿⠃⣿⣿⡗⠁
⣧⣿⣿⣧⢹⡀⠀⠀⠀⠱⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⠀⣴⣿⣿⣾⣿⣿⣿
⢿⠘⣿⣿⣿⣿⣤⠀⠢⡀⠱⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ ⠀⠀⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣠⣵⣿⣿⣿⣿⣿⣿⣿⣿⣷
⠀⠉⣿⣿⣿⡿⣿⠻⣷⣬⣓⣬⣄⠀⠀⠀⠀⠀⠀⠀ ⠀⠀⠉⠈⠈⠈⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣾⠃⠼⢉⣿⣿⣿⣿⣿⣿⣿
⠀⠀⣿⣿⣿⣷⠀⠀⠀⠘⣿⣄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣠⣾⣿⡏⠀⠀⢸⠀⢻⢿⣿⣿⡏⣿
⠀⢸⣿⣿⣿⣿⠀⠀⠀⠀⢻⣿⣿⣤⣀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣀⣴⣾⣿⣿⣿⣿⠀⠀⠀⢸⠀⠀⢸⣿⣿⠘⡀
⢦⡿⣿⣿⣿⢿⠀⠀⠀⠀⢸⣿⣿⣿⣿⣿⣿⣿⣶⣶⣦⡄⠀⠀⠀⠀⠀⠀⠀⠀⣰⣿⣿⣿⣿⣿⣿⣿⣿⠀⠀⠀⠘⡄⠀⠈⣿⣿⡄⠱
⣴⠛⣾⣿⣿⢸⠀⠀⠀⠀⠀⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠿⡄⠀⠀⠀⠀⠀⠀⠀⣯⠛⣿⣿⣿⣿⣿⣿⣿⠀⠀⠀⠀⣇⠀⠀⣿⣿⣿
⠿⠀⣿⣿⣿⠀⠀⠀⠀⠀⠀⣿⣿⣿⣿⣿⣿⣿⣿⠟⠰⡾⠃⠀⠀⠀⠀⠀⠀⠀⠙⡟⠀⢻⣿⣿⣿⣿⣿⡆⠀⠀⠀⠸⠀⠀⠸⣿⣿⣷
⠆⢳⣿⣿⡇⠀⠀⠀⠀⠀⠀⣿⣿⣿⠛⠿⠿⢿⡟⠀⠀⠉⠦⣀⡤⢶⠀⠖⠲⠶⠊⠀⠀⠀⢻⡛⠛⠛⣿⣿⠀⠀⠀⠀⠃⠀⠀⢿⣿⣿
*/

浙公网安备 33010602011771号