题目思路:这道题目其实跟插队那题线段树是一样的。
直接遍历就可以了
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
using namespace std;
#define MAX 200005
#define ls rt<<1
#define rs ls|1
#define m ((l+r)>>1)
int sum[MAX << 2][3];
int col[MAX << 2];
int posx[MAX];
int n, k;
struct node
{
int l, r, h, s;
node(){}
node(int _l, int _r, int _h, int _s)
{
l = _l;
r = _r;
h = _h;
s = _s;
}
bool operator<(node b)const
{
return h < b.h;
}
}p[MAX];
void uprt(int l, int r, int rt)
{
memset(sum[rt], 0, sizeof(sum[rt]));
if (col[rt] >= k)
{
sum[rt][k] = posx[r + 1] - posx[l];
return;
}
if (l == r)
{
sum[rt][col[rt]] = posx[r + 1] - posx[l];
}
else
{
int cur = col[rt];
for (int i = col[rt]; i < k; i++)
sum[rt][i] = sum[ls][i - cur] + sum[rs][i - cur];
for (int i = k - cur; i <= k; i++)
sum[rt][k] += sum[ls][i] + sum[rs][i];
}
}
void updata(int L, int R, int c, int l, int r, int rt)
{
if (L <= l&&r <= R)
{
col[rt] += c;
uprt(l, r, rt);
return;
}
int mid = m;
if (L <= mid)
updata(L, R, c, l, mid, ls);
if (mid < R)
updata(L, R, c, mid + 1, r, rs);
uprt(l, r, rt);
}
void build(int l, int r, int rt)
{
col[rt] = 0;
sum[rt][0] = posx[r + 1] - posx[l];//0次的时候默认是这样子。为了k>1的时候,需要传递
if (l == r)
return;
build(l, m, ls);
build(m + 1, r, rs);
}
int main()
{
int t;
cin >> t;
int icase = 1;
while (t--)
{
scanf("%d", &n);
k = 2;
memset(col, 0, sizeof(col));
memset(sum, 0, sizeof(sum));
int x1, x2, y1, y2;
int cnt = 0;
for (int i = 0; i < n; i++)
{
scanf("%d%d%d%d", &x1, &y1, &x2, &y2);
p[cnt] = node(x1, x2, y1, 1);
posx[cnt++] = x1;
p[cnt] = node(x1, x2, y2, -1);
posx[cnt++] = x2;
}
sort(posx, posx + cnt);
sort(p, p + cnt);
int cnt2 = unique(posx, posx + cnt) - posx;
long long ans = 0;
build(0, cnt2 - 1, 1);
for (int i = 0; i < cnt - 1; i++)
{
int curl = lower_bound(posx, posx + cnt2, p[i].l) - posx;
int curr = lower_bound(posx, posx + cnt2, p[i].r) - posx - 1;
if (curl <= curr)
updata(curl, curr, p[i].s, 0, cnt2 - 1, 1);
ans += (long long)(sum[1][1]) * (p[i + 1].h - p[i].h);
}
printf("Case %d: %lld\n", icase++, ans);
}
}