扫描线+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. [Windows Server 2012] Tomcat安装方法

    ★ 欢迎来到[护卫神·V课堂],网站地址:http://v.huweishen.com ★ 护卫神·V课堂 是护卫神旗下专业提供服务器教学视频的网站,每周更新视频. ★ 本节我们将带领大家:Win20 ...

  2. 重绘DataGridView标头

    最近突然想在DataGridView标头放置一个CheckBox,我就想着重写下DataGridViewColumnHeaderCell抱着试试的心态结果真的是可以的下面是源码:(如果有看不懂的可以加 ...

  3. servlet学习总结(一)——HttpServletRequest(转载)

    原文地址:http://www.cnblogs.com/xdp-gacl/p/3798347.html 一.HttpServletRequest介绍 HttpServletRequest对象代表客户端 ...

  4. Day 12 字符串和正则表达式

    使用正则表达式 正则表达式相关知识 在编写处理字符串的程序或网页时,经常会有查找符合某些复杂规则的字符串的需要,正则表达式就是用于描述这些规则的工具,换句话说正则表达式是一种工具,它定义了字符串的匹配 ...

  5. sysbench使用指南

    sysbench 安装.使用和测试 摘要: sysbench是一个开源的.模块化的.跨平台的多线程性能测试工具,可以用来进行CPU.内存.磁盘I/O.线程.数据库的性能测试.目前支持的数据库有MySQ ...

  6. adjtimex和时钟的几个概念tick,freq,ppm,jiffies

    adjtimex使用 今天遇到一个ntp的同步问题.服务器上配置好了ntpd,在启动前也手动进行过同步,但是过段时间ntpq查询发现服务器即便能选出同步服务器,但是系统的时间偏差越来越大. 服务器上实 ...

  7. select 多选 和单选,分组

    <select name="group"> <option value="1">北京</option> <option ...

  8. Git ——Tool

    Git: 何为Git: Git 是一个可以实时记录文件变化.维护文件的安全的一个仓库! Git仓库是由** Linux 系统之父 Linus Torvalds ** 创建的一个开源 的软件!Githu ...

  9. C++ API实现创建桌面快捷方式

    #include<windows.h> #include <string> #include <shellapi.h> #include <shlobj.h& ...

  10. qwb和李主席

    qwb和李主席 Time Limit: 4 Sec  Memory Limit: 128 MB Description qwb和李主席打算平分一堆宝藏,他们想确保分配公平,可惜他们都太懒了,你能帮助他 ...