扫描线+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. The type new View.OnClickListener(){} must implement the inherited abstract method View.Onclicklis

    public class MainActivity extends Activity { protected Button startBrew = null; @Override protected ...

  2. C语言保留字

    数值变量相关: int float double char long short unsigned signed 储存说明符 const 用于声明常量 static用于限制变量/函数的作用范围等等 e ...

  3. Java_Web三大框架之Hibernate+jsp+selvect+HQL注册用户

    Hibernate比SQL语句简单多了,代码冗余少,切方便简洁明了.下面用Hibernate+jsp+selvect+HQL来实现注册用户. 第一步:编写用户实体类和Users2.hbm.xml映射. ...

  4. Java_Web三大框架之Hibernate增删改查

    下面介绍一下Hibernate的增删改查. 第一步:编写用户实体类以及User.hbm.xml映射 package com.msl.entity; public class User { privat ...

  5. 【sqli-labs】 less54 GET -Challenge -Union -10 queries allowed -Variation1 (GET型 挑战 联合查询 只允许10次查询 变化1)

    尝试的次数只有10次 http://192.168.136.128/sqli-labs-master/Less-54/index.php?id=1' 单引号报错,错误信息没有显示 加注释符页面恢复正常 ...

  6. Node.js 命令行程序开发教程 ---------http://www.ruanyifeng.com/blog/2015/05/command-line-with-node.html

    五.yargs 模块 shelljs 只解决了如何调用 shell 命令,而 yargs 模块能够解决如何处理命令行参数.它也需要安装. $ npm install --save yargs yarg ...

  7. HTML 符号实体

    带有实体名称的 ASCII 实体 结果 描述 实体名称 实体编号 " quotation mark " " ' apostrophe  &apos; ' & ...

  8. div+css 组织结构

    <!DOCTYPE html><html><head> <meta charset="utf-8"> <title>家谱 ...

  9. Luogu P1892 [BOI2003]团伙

    P1892 [BOI2003]团伙 题目描述 1920年的芝加哥,出现了一群强盗.如果两个强盗遇上了,那么他们要么是朋友,要么是敌人.而且有一点是肯定的,就是: 我朋友的朋友是我的朋友: 我敌人的敌人 ...

  10. ansible使用jinja2管理配置文件以及jinja2语法简介

    一.Jinja2介绍 Jinja2是基于python的模板引擎,功能比较类似于PHP的smarty,J2ee的Freemarker和velocity.它能完全支持unicode,并具有集成的沙箱执行环 ...