扫描线+dp

先对坐标排序,然后·用set维护端点,每次插入左端点,扫描到右端点时删除。每次考虑新插入时分割了哪两个木板,自己分别连边,再删除原来的边,最后dp(好像得维护used,有环)

#include<bits/stdc++.h>
using namespace std;
typedef pair<int, int> PII;
const int N = , inf = ;
struct data {
int l, r, h;
data(int l = , int r = , int h = ) : l(l), r(r), h(h) {}
} ed[N];
int n, t, cnt;
int dp[N], used[N];
PII e[N];
set<PII> s, m;
vector<PII> G[N];
void dfs(int u)
{
if(dp[u] == inf || used[u]) return;
used[u] = ;
for(int i = ; i < G[u].size(); ++i)
{
PII x = G[u][i];
int v = x.first, w = x.second;
dfs(v);
dp[u] = max(dp[u], min(dp[v], w));
}
}
int main()
{
scanf("%d%d", &n, &t);
for(int i = ; i <= n; ++i)
{
int h, l, r; scanf("%d%d%d", &h, &l, &r);
ed[i] = data(l, r, h);
e[++cnt] = make_pair(l, i);
e[++cnt] = make_pair(r, -i);
}
sort(e + , e + cnt + );
ed[n + ] = data(-inf, inf, );
ed[n + ] = data(-inf, inf, t);
s.insert(make_pair(, n + ));
s.insert(make_pair(t, n + ));
for(int i = ; i <= cnt; ++i)
{
int x = e[i].second;
if(x < )
{
s.erase(make_pair(ed[-x].h, -x));
continue;
}
PII t = make_pair(ed[x].h, x);
set<PII> :: iterator it = s.lower_bound(t);
PII up = *it;
--it;
PII low = *it;
m.erase(make_pair(up.second, low.second));
m.insert(make_pair(up.second, x));
m.insert(make_pair(x, low.second));
s.insert(t);
}
for(set<PII> :: iterator it = m.begin(); it != m.end(); ++it)
{
PII x = *it;
int len = min(ed[x.second].r, ed[x.first].r) - max(ed[x.second].l, ed[x.first].l);
G[x.second].push_back(make_pair(x.first, len));
}
dp[n + ] = inf;
dfs(n + );
printf("%d\n", dp[n + ]);
return ;
}

线段树维护+dp

这个方法好恶心,调了好长时间,边界搞错。

先离散化坐标,然后按高度排序,正反两次建边。但是一定要注意,边界很恶心,有可能出现1-2,2-3这样的,这样是不相交的。所以右端点要-1就避免了这种情况,因为如果原先只有1单位重合,那么现在不相交了。如果有1单位以上重合,那么现在还是相交的。

#include<bits/stdc++.h>
using namespace std;
typedef pair<int, int> PII;
const int M = , inf = ;
int n, T, N;
vector<PII> G[M];
vector<int> v;
map<int, int> mp, mir;
int dp[M], used[M];
struct data {
int l, r, h;
} a[M];
struct seg {
int tree[M << ], tag[M << ];
void pushdown(int x)
{
if(!tag[x]) return;
tag[x << ] = tag[x];
tag[x << | ] = tag[x];
tree[x << ] = tag[x];
tree[x << | ] = tag[x];
tag[x] = ;
}
void update(int l, int r, int x, int a, int b, int c)
{
if(l > b || r < a) return;
if(l >= a && r <= b)
{
tree[x] = tag[x] = c;
return;
}
pushdown(x);
int mid = (l + r) >> ;
update(l, mid, x << , a, b, c);
update(mid + , r, x << | , a, b, c);
tree[x] = max(tree[x << ], tree[x << | ]);
}
int query(int l, int r, int x, int a, int b)
{
if(l > b || r < a) return ;
if(l >= a && r <= b) return tree[x];
pushdown(x);
int mid = (l + r) >> ;
return max(query(l, mid, x << , a, b), query(mid + , r, x << | , a, b));
}
} t;
void construct(int N, bool flag)
{
memset(t.tree, , sizeof(t.tree));
memset(t.tag, , sizeof(t.tag));
for(int i = ; i < n; ++i)
{
int k = t.query(, N, , a[i].l, a[i].l);
int low = max(a[i].l, a[k].l), high = min(a[i].r, a[k].r), len = mir[high] - mir[low];
int tt = t.query(, N, , low, high - );
if(tt == k && tt)
{
if(!flag) G[k].push_back(make_pair(i, len));
else G[n - i + ].push_back(make_pair(n - k + , len));
}
k = t.query(, N, , a[i].r - , a[i].r - );
low = max(a[i].l, a[k].l), high = min(a[i].r, a[k].r), len = mir[high] - mir[low];
tt = t.query(, N, , low, high - );
if(tt == k && tt)
{
if(!flag) G[k].push_back(make_pair(i, len));
else G[n - i + ].push_back(make_pair(n - k + , len));
}
t.update(, N, , a[i].l, a[i].r - , i);
}
}
void dfs(int u)
{
if(used[u] || dp[u] == inf) return;
used[u] = ;
for(int i = ; i < G[u].size(); ++i)
{
PII x = G[u][i];
int v = x.first, w = x.second;
dfs(v);
dp[u] = max(dp[u], min(dp[v], w));
}
}
bool cp(data x, data y)
{
return x.h == y.h ? x.l < y.l : x.h < y.h;
}
int main()
{
scanf("%d%d", &n, &T);
a[].h = ;
a[n + ].h = T;
a[].l = a[n + ].l = -inf;
a[].r = a[n + ].r = inf;
v.push_back(inf);
v.push_back(-inf);
for(int i = ; i <= n; ++i)
{
scanf("%d%d%d", &a[i + ].h, &a[i + ].l, &a[i + ].r);
v.push_back(a[i + ].l);
v.push_back(a[i + ].r);
}
sort(v.begin(), v.end());
v.erase(unique(v.begin(), v.end()), v.end());
N = v.size();
for(int i = ; i < v.size(); ++i)
{
mp[v[i]] = i + ;
mir[i + ] = v[i];
}
n += ;
for(int i = ; i <= n; ++i)
{
a[i].l = mp[a[i].l];
a[i].r = mp[a[i].r];
}
sort(a + , a + n + , cp);
construct(N, false);
reverse(a + , a + n + );
construct(N, true);
dp[n] = inf;
dfs();
printf("%d\n", dp[]);
return ;
}

269D的更多相关文章

  1. 269D Maximum Waterfall

    传送门 题目大意 给出一些墙,水从高往低流,每次只能到达一面墙,选择一个路径,使得路径上的流量的最小值最大. 分析 这是一道经典的扫描线题,我们发现能够合法的线段对数至多只有n对.将一条线段拆成两个点 ...

  2. PLSQL_Oracle Exception异常分类、异常抛出、异常处理、异常传播(概念)

    2014-06-03 Created By BaoXinjian

  3. javaWeb面试题(重要)

    1.Javaweb 技术的结构  1.1 技术结构图

随机推荐

  1. JS——scroll封装

    DTD未声明:document.body.scrollTop DTD已声明:document.documentElement.scrollTop 火狐谷歌IE9:window.pageYOffset ...

  2. HDU_1028_Ignatius and the Princess III_(母函数,dp)

    Ignatius and the Princess III Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K ...

  3. Windows 8 常见教程

    http://www.codeproject.com/Articles/439874/Web-service-on-Windows-Phone http://www.c-sharpcorner.com ...

  4. SpringBoot启动报jdbc连接池错误

    如图,启动报连接池错误 项目中没有使用任何连接池,以为没用连接池的原因,所以配置了druid,一开始可以正常启动,但后来重启项目时仍旧报同样的错.网上找了资料,url中加useSSL=false,显式 ...

  5. Windows下Unity安装

    安装教程: https://www.paws3d.com/lesson/us-0101/ 问题1: 安装并完成注册后,在网页上能登录,但打开Unity时不能启动成功,一直停留在如下界面 解决方案:断网 ...

  6. 25.TF&IDF算法以及向量空间模型算法

    主要知识点: boolean model IF/IDF vector space model     一.boolean model     在es做各种搜索进行打分排序时,会先用boolean mo ...

  7. Git下的标签

    发布一个版本时,我们通常先在版本库中打一个标签(tag),这样,就唯一确定了打标签时刻的版本.将来无论什么时候,取某个标签的版本,就是把那个打标签的时刻的历史版本取出来.所以,标签也是版本库的一个快照 ...

  8. 搭建 Seafile 专属网盘

    准备域名 任务时间:15min ~ 20min 域名注册 如果您还没有域名,可以在腾讯云上选购,过程可以参考下面的视频. 视频 - 在腾讯云上购买域名 域名解析 域名购买完成后, 需要将域名解析到实验 ...

  9. 使用androidstudio 分析内存泄漏

    分析内存泄漏 http://www.jianshu.com/p/c49f778e7acf

  10. 【codeforces 796B】Find The Bone

    [题目链接]:http://codeforces.com/contest/796/problem/B [题意] 一开始骨头在1号位置; 然后有m个洞,给出洞的下标; 然后有k个交换操作; 如果骨头到洞 ...