[POI2015]PUS
嘟嘟嘟
这题只要往正确的方面想,就很简单。
首先,这是一道图论题!
想到这,这题就简单了。对于两个数\(i\)和\(j\),如果\(i\)比\(j\)大,就从\(i\)向\(j\)连边。然后如果图中存在环的话就无解,否则DAG上dp就完事啦。
但是如果暴力连边,最高就能达到\(O(k ^ 3)\)复杂度。然后考虑到是向连续区间连边,就可以线段树优化建图了。
我刚开始就这么写的,过是过了,但后来看题解才发现我这最坏也能达到\(O(n ^ 2logn)\)复杂度,实际上应该把这\(k\)个点向一个虚拟结点连边权为1的边,然后虚拟点向区间连边权为0的边,就能避免两两匹配\(O(n ^ 2)\)了。
就放一个我刚开始写的不太完美的代码吧,题解说的懒得写了。
19.7.8update,关于找环,直接拓扑排序,最后看还有没有入度为0的点就行了。(看以前的代码,还多写了个tarjan缩点,判联通块点数是否大于1……麻烦了)
#include<cstdio>
#include<iostream>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<cstdlib>
#include<cctype>
#include<vector>
#include<stack>
#include<queue>
using namespace std;
#define enter puts("")
#define space putchar(' ')
#define Mem(a, x) memset(a, x, sizeof(a))
#define In inline
typedef long long ll;
typedef double db;
const int INF = 1e9;
const db eps = 1e-8;
const int maxn = 2e5 + 5;
const int maxN = 4e6 + 5;
const int maxe = 5e6 + 5;
inline ll read()
{
ll ans = 0;
char ch = getchar(), last = ' ';
while(!isdigit(ch)) last = ch, ch = getchar();
while(isdigit(ch)) ans = (ans << 1) + (ans << 3) + ch - '0', ch = getchar();
if(last == '-') ans = -ans;
return ans;
}
inline void write(ll x)
{
if(x < 0) x = -x, putchar('-');
if(x >= 10) write(x / 10);
putchar(x % 10 + '0');
}
int n, m, s, val[maxn], pos[maxn], du[maxN];
struct Edge
{
int nxt, to, w;
}e[maxe];
int head[maxN], ecnt = -1;
In void addEdge(int x, int y, int w)
{
++du[y];
e[++ecnt] = (Edge){head[x], y, w};
head[x] = ecnt;
}
int l[maxn << 2], r[maxn << 2], tIn[maxn << 2], tcnt = 0;
In void build(int L, int R, int now)
{
l[now] = L; r[now] = R;
if(L == R) {tIn[now] = L; return;}
tIn[now] = ++tcnt;
int mid = (L + R) >> 1;
build(L, mid, now << 1);
build(mid + 1, R, now << 1 | 1);
addEdge(tIn[now], tIn[now << 1], 0);
addEdge(tIn[now], tIn[now << 1 | 1], 0);
}
In void update(int L, int R, int now, int x, int w)
{
if(L > R) return;
if(l[now] == L && r[now] == R)
{
addEdge(x, tIn[now], w);
return;
}
int mid = (l[now] + r[now]) >> 1;
if(R <= mid) update(L, R, now << 1, x, w);
else if(L > mid) update(L, R, now << 1 | 1, x, w);
else update(L, mid, now << 1, x, w), update(mid + 1, R, now << 1 | 1, x, w);
}
int dp[maxN];
In bool topo()
{
fill(dp + 1, dp + tcnt + 1, INF);
queue<int> q;
for(int i = 1; i <= tcnt; ++i) if(!du[i]) q.push(i);
while(!q.empty())
{
int now = q.front(); q.pop();
if(val[now])
{
if(dp[now] < val[now]) return 0;
dp[now] = val[now];
}
for(int i = head[now], v; ~i; i = e[i].nxt)
{
v = e[i].to;
dp[v] = min(dp[v], dp[now] - e[i].w);
if(!--du[v]) q.push(v);
}
}
for(int i = 1; i <= tcnt; ++i) if(du[i]) return 0;
return 1;
}
int main()
{
// freopen("ha.in", "r", stdin);
// freopen("ha.out", "w", stdout);
Mem(head, -1);
n = read(), s = read(), m = read();
for(int i = 1, x; i <= s; ++i) x = read(), val[x] = read();
tcnt = n; build(1, n, 1);
for(int i = 1; i <= m; ++i)
{
int L = read(), R = read(), K = read();
pos[0] = L - 1;
for(int j = 1; j <= K; ++j) pos[j] = read();
for(int j = 1; j <= K; ++j)
{
for(int k = 1; k <= K; ++k)
update(pos[k - 1] + 1, pos[k] - 1, 1, pos[j], 1);
update(pos[K] + 1, R, 1, pos[j], 1);
}
}
if(!topo()) {puts("NIE"); return 0;}
puts("TAK");
for(int i = 1; i <= n; ++i) write(val[i] ? val[i] : dp[i]), space; enter;
return 0;
}
[POI2015]PUS的更多相关文章
- P3588 [POI2015]PUS(拓扑排序+线段树)
P3588 [POI2015]PUS 对于每个$(l,r,k)$,将$k$个位置向剩下$r-l-k+1$个位置连边,边权为$1$,这样就保证$k$个位置比剩下的大 先给所有位置填$1e9$保证最优 然 ...
- P3588 【[POI2015]PUS】(线段树优化建边)
P3588 [[POI2015]PUS] 终于有个能让我一遍过的题了,写篇题解纪念一下 给定长度为n的序列和其中部分已知的数,还有m个大小关系:区间\([l,r]\)中,有k个给定的数比剩下的\(r- ...
- 洛谷P3588 [POI2015]PUS
题面 sol:说了是线段树优化建图的模板... 就是把一整个区间的点连到一个点上,然后用那个点来连需要连一整个区间的点就可以了,就把边的条数优化成n*log(n)了 #include <queu ...
- 洛谷P3588 [POI2015]PUS(线段树优化建图)
题面 传送门 题解 先考虑暴力怎么做,我们把所有\(r-l+1-k\)中的点向\(x\)连有向边,表示\(x\)必须比它们大,那么如果这张图有环显然就无解了,否则的话我们跑一个多源最短路,每个点的\( ...
- luoguP3588_[POI2015]PUS
题意 有一个\(n\)个数的序列,已知其中的\(k\)个数,然后有\(m\)个信息,每个信息给出区间\([l,r]\),和\(k\)个数,表示区间\([l,r]\)中这\(k\)个数大于剩下的\(r- ...
- P3588 [POI2015]PUS
好题 思路:线段树优化建图+拓扑DP or 差分约束(都差不多): 提交:3次 错因:眼瞎没看题,Inf写的0x3f3f3f3f 题解: 类似差分约束的模型,\(a<b\rightarrow a ...
- [POI2015]PUS [线段树优化建图]
problem 线段树优化建图,拓扑,没了. #include <bits/stdc++.h> #define ls(x) ch[x][0] #define rs(x) ch[x][1] ...
- POI2015 解题报告
由于博主没有BZOJ权限号, 是在洛咕做的题~ 完成了13题(虽然有一半难题都是看题解的QAQ)剩下的题咕咕咕~~ Luogu3585 [POI2015]PIE Solution 模拟, 按顺序搜索, ...
- Luogu P3783 [SDOI2017]天才黑客
题目大意 一道码量直逼猪国杀的图论+数据结构题.我猪国杀也就一百来行 首先我们要看懂鬼畜的题意,发现其实就是在一个带权有向图上,每条边有一个字符串信息.让你找一个点出发到其它点的最短路径.听起来很简单 ...
随机推荐
- 数据库 【redis】 命令大全
以下纯属搬砖,我用Python抓取的redis命令列表页内容 如果想看命令的具体使用可查去官网查看,以下整理为个人查找方便而已 地理位置GEOADD 将指定的地理空间位置(纬度.经度.名称)添加到指定 ...
- AutoHotkey 自动化脚本工具实例
AHK 自动按键工具 https://www.autohotkey.com/ 可实现功能 快捷键 启动 浏览器.CMD命令.弹出框 可定时执行任务 可改键 将A与B互换 可快捷替换字符串 测试如下: ...
- .NET之微信消息模板推送
最近在项目中使用到了微信消息模板推送的功能,也就是将对应的消息推送到对应的用户微信上去,前提是你必须要有一个微信公众号并且是付费了的才会有这个功能,还有就是要推送的用户必须是的关注了你的微信公众号的. ...
- ES6 模块化笔记
ES6 模块的设计思想,是尽量的静态化,使得编译时就能确定模块的依赖关系,以及输入和输出的变量. ES6 模块不是对象,而是通过export命令显式指定输出的代码,再通过import命令输入. // ...
- 使用 Parallels Destop 最小化安装 centOS 操作系统
1. 环境准备 macOS 操作系统 Parallels Destop 13 CentOS 7.6 Minimal ISO 镜像文件 2. 新建操作系统 选择下载好的 CentosOS 7.6 即 C ...
- Spring Cloud Eureka 注册中心集群搭建,Greenwich 最新版!
Spring Cloud 的注册中心可以由 Eureka.Consul.Zookeeper.ETCD 等来实现,这里推荐使用 Spring Cloud Eureka 来实现注册中心,它基于 Netfl ...
- Java中Map和Object的互相转换方式
一.使用Apache中的BeanUtils类,导入commons-beanutils包. Jar包Maven下载地址:https://mvnrepository.com/artifact/common ...
- Docker 搜索镜像
文章首发个人网站: https://www.exception.site/docker/docker-search-image 本文中,您将学习 Docker 如何搜索镜像? 一.search 命令 ...
- async/await使用深入详解
async和await作为异步模型代码编写的语法糖已经提供了一段时间不过一直没怎么用,由于最近需要在BeetleX webapi中集成对Task方法的支持,所以对async和await有了深入的了解和 ...
- 尴尬的事情又发生Newtonsoft.Json vs Protobuf.net
写程序做下性能测试都是例行的事情了,一般在普通电脑上测试一下如果比较理想那基本不出什么意外!但世事难料,代码写得不好经常担心CPU不够用,其实写得好但不能完全发挥出CPU资源的优势更是一件悲剧的事情! ...