扫描线+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. Zabbix 客户端安装教程(第二篇)

    Zabbix 客户端安装教程 blog地址:http://www.cnblogs.com/caoguo [root@localhost ~]# yum install -y gcc make [roo ...

  2. C# 统计字符串出现的个数

    string str1 = "123AAA456AAAA789AAAAAAA1011"; string str2 = "123456789AAA23456789AAAA3 ...

  3. EF入门

    1.(安装EF)右键项目

  4. PAT_A1107#Social Clusters

    Source: PAT A1107 Social Clusters (30 分) Description: When register on a social network, you are alw ...

  5. EAS之校验检查

    先了解一下权限接口类提供的有关权限项检查的方法public boolean hasFunctionPermission(IObjectPK userPK,IObjectPK orgPK,String ...

  6. [系统资源攻略]CPU使用率和负载

    我们在搞性能测试的时候,对后台服务器的CPU利用率监控是一个常用的手段.服务器的CPU利用率高,则表明服务器很繁忙.如果前台响应时间越来越大,而后台CPU利用率始终上不去,说明在某个地方有瓶颈了,系统 ...

  7. Problem 56

    Problem 56 https://projecteuler.net/problem=56 Powerful digit sum A googol (10100) is a massive numb ...

  8. BZOJ 2754 [SCOI2012]喵星球上的点名 (AC自动机、树状数组)

    吐槽: 为啥很多人用AC自动机暴力跳都过了?复杂度真的对么? 做法一: AC自动机+树状数组 姓名的问题,中间加个特殊字符连起来即可. 肯定是对点名串建AC自动机(map存儿子),然后第一问就相当于问 ...

  9. noip模拟赛 浮游大陆的68号岛

    题目描述 妖精仓库里生活着黄金妖精们,她们过着快乐,却随时准备着迎接死亡的生活. 换用更高尚的说法,是随时准备着为这个无药可救的世界献身. 然而孩子们的生活却总是无忧无虑的,幼体的黄金妖精们过着天真烂 ...

  10. hdu 4081 最小生成树变形

    /*关于最小生成树的等效边,就是讲两个相同的集合连接在一起 先建立一个任意最小生成树,这条边分开的两个子树的节点最大的一个和为A,sum为最小生成树的权值和,B为sum-当前边的权值 不断枚举最小生成 ...