上午,强开女神,瘫软在地
下午,怒写体积交
晚上,试水匈牙利
区间合并的问题,只是要维护两组的变量,这两组的变量有优先级的差异,才用的是两颗线段树各维护一组变量的技巧,减少了代码规模,其实想写一个基类,两个子类,继承重载的方法
注意!
1.在区间合并中,用query把长度转换成具体的[l, r]区间,可以大大较少update里面的思维复杂度
2.push_down 与 push_up只有全空与全满的情况,因为在几种update中只有全空、全满的更新,没有其他的
(正是因为陷入了半满的怪圈,才导致强上女神而不得)
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;
const int maxn = 100000 + 10;
struct SegTree
{
int l, r;
int left_time, max_time, right_time;
void init(int l, int r)
{
this->l = l, this->r = r;
left_time = max_time = right_time = r - l + 1;
}
}goddess_segTree[maxn << 2], friend_segTree[maxn << 2];
int t, n;
void build(int k, int l, int r)
{
goddess_segTree[k].init(l, r);
friend_segTree[k].init(l, r);
if (l == r) return;
int m = (l + r) >> 1;
build(k << 1, l, m);
build(k << 1 | 1, m + 1, r);
}
int query(int k, SegTree * segTree, int len)
{
if (segTree[k].left_time >= len) return segTree[k].l;
if (segTree[k << 1].max_time >= len) return query(k << 1, segTree, len);
if (segTree[k << 1].right_time + segTree[k << 1 | 1].left_time >= len)
return segTree[k << 1].r - segTree[k << 1].right_time + 1;
return query(k << 1 | 1, segTree, len);
}
void push_down(int k)
{
if (friend_segTree[k].l == friend_segTree[k].r) return;
if (friend_segTree[k].max_time == 0)
{
friend_segTree[k << 1].left_time = friend_segTree[k << 1].max_time
= friend_segTree[k << 1].right_time = 0;
friend_segTree[k << 1 | 1].left_time = friend_segTree[k << 1 | 1].max_time
= friend_segTree[k << 1 | 1].right_time = 0;
}
if (friend_segTree[k].max_time == friend_segTree[k].r - friend_segTree[k].l + 1)
{
friend_segTree[k << 1].left_time = friend_segTree[k << 1].max_time = friend_segTree[k << 1].right_time
= friend_segTree[k << 1].r - friend_segTree[k << 1].l + 1;
friend_segTree[k << 1 | 1].left_time = friend_segTree[k << 1 | 1].max_time = friend_segTree[k << 1 | 1].right_time
= friend_segTree[k << 1 | 1].r - friend_segTree[k << 1 | 1].l + 1;
}
//_________________________________________________________________________
if (goddess_segTree[k].max_time == 0)
{
goddess_segTree[k << 1].left_time = goddess_segTree[k << 1].max_time
= goddess_segTree[k << 1].right_time = 0;
goddess_segTree[k << 1 | 1].left_time = goddess_segTree[k << 1 | 1].max_time
= goddess_segTree[k << 1 | 1].right_time = 0;
}
if (goddess_segTree[k].max_time == goddess_segTree[k].r - goddess_segTree[k].l + 1)
{
goddess_segTree[k << 1].left_time = goddess_segTree[k << 1].max_time = goddess_segTree[k << 1].right_time
= goddess_segTree[k << 1].r - goddess_segTree[k << 1].l + 1;
goddess_segTree[k << 1 | 1].left_time = goddess_segTree[k << 1 | 1].max_time = goddess_segTree[k << 1 | 1].right_time
= goddess_segTree[k << 1 | 1].r - goddess_segTree[k << 1 | 1].l + 1;
}
}
void push_up(int k)
{
if (friend_segTree[k].l == friend_segTree[k].r) return;
friend_segTree[k].left_time = friend_segTree[k << 1].left_time;
if (friend_segTree[k << 1].l + friend_segTree[k << 1].left_time - 1 == friend_segTree[k << 1].r)
friend_segTree[k].left_time += friend_segTree[k << 1 | 1].left_time;
friend_segTree[k].right_time = friend_segTree[k << 1 | 1].right_time;
if (friend_segTree[k << 1 | 1].r - friend_segTree[k << 1 | 1].right_time + 1 == friend_segTree[k << 1 | 1].l)
friend_segTree[k].right_time += friend_segTree[k << 1].right_time;
friend_segTree[k].max_time = max(friend_segTree[k << 1].max_time, friend_segTree[k << 1 | 1].max_time);
friend_segTree[k].max_time = max(friend_segTree[k].max_time,
friend_segTree[k << 1].right_time + friend_segTree[k << 1 | 1].left_time);
//_________________________________________________________________________
goddess_segTree[k].left_time = goddess_segTree[k << 1].left_time;
if (goddess_segTree[k << 1].l + goddess_segTree[k << 1].left_time - 1 == goddess_segTree[k << 1].r)
goddess_segTree[k].left_time += goddess_segTree[k << 1 | 1].left_time;
goddess_segTree[k].right_time = goddess_segTree[k << 1 | 1].right_time;
if (goddess_segTree[k << 1 | 1].r - goddess_segTree[k << 1 | 1].right_time + 1 == goddess_segTree[k << 1 | 1].l)
goddess_segTree[k].right_time += goddess_segTree[k << 1].right_time;
goddess_segTree[k].max_time = max(goddess_segTree[k << 1].max_time, goddess_segTree[k << 1 | 1].max_time);
goddess_segTree[k].max_time = max(goddess_segTree[k].max_time,
goddess_segTree[k << 1].right_time + goddess_segTree[k << 1 | 1].left_time);
}
void update(int k, int l, int r, int flag)
{
if (l > friend_segTree[k].r || r < friend_segTree[k].l) return;
if (l <= friend_segTree[k].l && friend_segTree[k].r <= r)
{
friend_segTree[k].left_time = friend_segTree[k].max_time
= friend_segTree[k].right_time = 0;
if (flag)
{
goddess_segTree[k].left_time = goddess_segTree[k].max_time
= goddess_segTree[k].right_time = 0;
}
return;
}
push_down(k);
update(k << 1, l, r, flag);
update(k << 1 | 1, l, r, flag);
push_up(k);
}
void solve_ds(int len)
{
if (friend_segTree[1].max_time >= len)
{
int beg = query(1, friend_segTree, len);
printf("%d,let's fly\n", beg);
update(1, beg, beg + len - 1, 0);
return;
}
puts("fly with yourself");
}
void solve_ns(int len)
{
if (friend_segTree[1].max_time >= len)
{
int beg = query(1, friend_segTree, len);
printf("%d,don't put my gezi\n", beg);
update(1, beg, beg + len - 1, 1);
return;
}
if (goddess_segTree[1].max_time >= len)
{
int beg = query(1, goddess_segTree, len);
printf("%d,don't put my gezi\n", beg);
update(1, beg, beg + len - 1, 1);
return;
}
puts("wait for me");
}
void update_study(int k, int l, int r)
{
if (l > friend_segTree[k].r || r < friend_segTree[k].l) return;
if (l <= friend_segTree[k].l && friend_segTree[k].r <= r)
{
friend_segTree[k].left_time = friend_segTree[k].max_time = friend_segTree[k].right_time
= friend_segTree[k].r - friend_segTree[k].l + 1;
goddess_segTree[k].left_time = goddess_segTree[k].max_time = goddess_segTree[k].right_time
= goddess_segTree[k].r - goddess_segTree[k].l + 1;
return;
}
push_down(k);
update_study(k << 1, l, r);
update_study(k << 1 | 1, l, r);
push_up(k);
}
void solve_study(int l, int r)
{
puts("I am the hope of chinese chengxuyuan!!");
update_study(1, l, r);
}
int main()
{
int ttt; scanf("%d", &ttt);
int kase = 0;
while (ttt--)
{
printf("Case %d:\n", ++kase);
scanf("%d%d", &t, &n);
build(1, 1, t);
for (int i = 0; i < n; i++)
{
char cmd[10];
int a, b;
scanf("%s%d", cmd, &a);
if (cmd[0] == 'D') solve_ds(a);
else if (cmd[0] == 'N') solve_ns(a);
else if (cmd[0] == 'S')
{
scanf("%d", &b);
solve_study(a, b);
}
}
}
return 0;
}
这种代码仿佛是在写项目….
周长交 -> 面积交 -> 体积交
一维 二维 三维
一维的周长中,差值来计算
二维的面积中,pre_len * deta_h
三维的体积中,以体积层为枚举单位,利用当前层内的面积 * deta_z
主要难点在于枚举体积层,其他的,比如重合三次,因为刚刚完成了面积交,所以很顺畅
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#include <algorithm>
using namespace std;
typedef long long ll;
const int maxn = 3000 + 10;
struct Line
{
ll l, r, h;
ll z1, z2;
ll flag;
Line(ll l = 0, ll r = 0, ll h = 0, ll z1 = 0, ll z2 = 0, ll flag = 0)
{
this->l = l, this->r = r, this->h = h, this->z1 = z1, this->z2 = z2, this->flag = flag;
}
bool operator < (const Line & rhs) const
{
return h < rhs.h;
}
}line[maxn];
struct SegTree
{
ll l, r;
ll cnt;
ll sum1, sum2, sum3;
void init(ll l, ll r)
{
this->l = l, this->r = r;
sum1 = sum2 = sum3 = 0;
cnt = 0;
}
}segTree[maxn << 2];
ll new_x[maxn], new_z[maxn];
ll cur1;
void build(int k, ll l, ll r)
{
segTree[k].init(l, r);
if (l + 1 >= r) return;
ll m = (l + r) >> 1;
build(k << 1, l, m);
build(k << 1 | 1, m, r);
}
ll depress_x()
{
vector<ll> pool;
for (int i = 0; i < cur1; i++)
{
pool.push_back(line[i].l);
pool.push_back(line[i].r);
}
sort(pool.begin(), pool.end());
pool.erase(unique(pool.begin(), pool.end()), pool.end());
for (int i = 0; i < cur1; i++)
{
ll cur;
cur = find(pool.begin(), pool.end(), line[i].l) - pool.begin();
new_x[cur] = line[i].l; line[i].l = cur;
cur = find(pool.begin(), pool.end(), line[i].r) - pool.begin();
new_x[cur] = line[i].r; line[i].r = cur;
}
return pool.size() - 1;
}
ll depress_z()
{
vector<ll> pool;
for (int i = 0; i < cur1; i++)
{
pool.push_back(line[i].z1);
pool.push_back(line[i].z2);
}
sort(pool.begin(), pool.end());
pool.erase(unique(pool.begin(), pool.end()), pool.end());
for (int i = 0; i < cur1; i++)
{
ll cur;
cur = find(pool.begin(), pool.end(), line[i].z1) - pool.begin();
new_z[cur] = line[i].z1;
cur = find(pool.begin(), pool.end(), line[i].z2) - pool.begin();
new_z[cur] = line[i].z2;
}
return pool.size() - 1;
}
void chan_sum(int k)
{
if (segTree[k].cnt >= 3)
{
segTree[k].sum3 = new_x[segTree[k].r] - new_x[segTree[k].l];
segTree[k].sum2 = new_x[segTree[k].r] - new_x[segTree[k].l];
segTree[k].sum1 = new_x[segTree[k].r] - new_x[segTree[k].l];
}
else if (segTree[k].cnt == 2)
{
segTree[k].sum3 = segTree[k << 1].sum1 + segTree[k << 1 | 1].sum1;
segTree[k].sum2 = new_x[segTree[k].r] - new_x[segTree[k].l];
segTree[k].sum1 = new_x[segTree[k].r] - new_x[segTree[k].l];
}
else if (segTree[k].cnt == 1)
{
segTree[k].sum3 = segTree[k << 1].sum2 + segTree[k << 1 | 1].sum2;
segTree[k].sum2 = segTree[k << 1].sum1 + segTree[k << 1 | 1].sum1;
segTree[k].sum1 = new_x[segTree[k].r] - new_x[segTree[k].l];
}
else if (segTree[k].cnt == 0)
{
segTree[k].sum3 = segTree[k << 1].sum3 + segTree[k << 1 | 1].sum3;
segTree[k].sum2 = segTree[k << 1].sum2 + segTree[k << 1 | 1].sum2;
segTree[k].sum1 = segTree[k << 1].sum1 + segTree[k << 1 | 1].sum1;
}
}
void update(int k, ll l, ll r, ll c)
{
if (l > segTree[k].r || r < segTree[k].l) return;
if (l <= segTree[k].l && segTree[k].r <= r)
{
segTree[k].cnt += c;
chan_sum(k);
return;
}
if (segTree[k].l + 1 == segTree[k].r)
{
if (segTree[k].cnt >= 3)
{
segTree[k].sum3 = new_x[segTree[k].r] - new_x[segTree[k].l];
segTree[k].sum2 = new_x[segTree[k].r] - new_x[segTree[k].l];
segTree[k].sum1 = new_x[segTree[k].r] - new_x[segTree[k].l];
}
else if (segTree[k].cnt == 2)
{
segTree[k].sum3 = 0;
segTree[k].sum2 = new_x[segTree[k].r] - new_x[segTree[k].l];
segTree[k].sum1 = new_x[segTree[k].r] - new_x[segTree[k].l];
}
else if (segTree[k].cnt == 1)
{
segTree[k].sum3 = 0;
segTree[k].sum2 = 0;
segTree[k].sum1 = new_x[segTree[k].r] - new_x[segTree[k].l];
}
else if (segTree[k].cnt == 0)
{
segTree[k].sum3 = 0;
segTree[k].sum2 = 0;
segTree[k].sum1 = 0;
}
return;
}
update(k << 1, l, r, c);
update(k << 1 | 1, l, r, c);
chan_sum(k);
}
ll square(ll down_lim, ll up_lim)
{
ll pre_h = 0, pre_len = 0;
ll res = 0;
for (int i = 0; i < cur1; i++)
{
if (line[i].z1 <= down_lim && up_lim <= line[i].z2)
{
update(1, line[i].l, line[i].r, line[i].flag);
res += (line[i].h - pre_h) * pre_len;
pre_h = line[i].h;
pre_len = segTree[1].sum3;
}
}
return res;
}
ll solve()
{
ll w_x = depress_x();
ll w_z = depress_z();
ll res = 0;
for (int i = 1; i <= w_z; i++)
{
build(1, 0, w_x);
ll down_lim = new_z[i - 1];
ll up_lim = new_z[i];
res += (up_lim - down_lim) * square(down_lim, up_lim);
}
return res;
}
int main()
{
int t; scanf("%d", &t);
int kase = 0;
while (t--)
{
cur1 = 0;
int n; scanf("%d", &n);
for (int i = 0; i < n; i++)
{
ll xx1, yy1, zz1, xx2, yy2, zz2;
scanf("%lld%lld%lld%lld%lld%lld", &xx1, &yy1, &zz1, &xx2, &yy2, &zz2);
line[cur1++] = Line(xx1, xx2, yy1, zz1, zz2, 1);
line[cur1++] = Line(xx1, xx2, yy2, zz1, zz2, -1);
}
sort(line, line + cur1);
printf("Case %d: %lld\n", ++kase, solve());
}
return 0;
}
复习了匈牙利算法,难为我还能记得,然而建模上面缺乏经验,被队友随意摩擦