[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]天才黑客
题目大意 一道码量直逼猪国杀的图论+数据结构题.我猪国杀也就一百来行 首先我们要看懂鬼畜的题意,发现其实就是在一个带权有向图上,每条边有一个字符串信息.让你找一个点出发到其它点的最短路径.听起来很简单 ...
随机推荐
- chrome谷歌开发者工具(hover时候的css样式怎么在浏览器调试)
很多小伙伴在开发的时候,大多是在用谷歌开发者工具调试代码(快捷键F12 或 Ctrl-Shift-i). 可能会经常遇到需要调试hover样式的时候,一般都是直接改代码,然后在页面上刷新查看效果. 其 ...
- 网卡的 Ring Buffer 详解
1. 网卡处理数据包流程 网卡处理网络数据流程图: 图片来自参考链接1 上图中虚线步骤的解释: DMA 将 NIC 接收的数据包逐个写入 sk_buff ,一个数据包可能占用多个 sk_buff , ...
- Mac电脑上一款非常时尚高清的动态壁纸Living Wallpaper HD
很多朋友Mac电脑上都喜欢用动态壁纸,Living Wallpaper HD是本人尝试的一款非常不错的高清动态壁纸.有时钟.天气等各种组建,非常时尚美观. Living Wallpaper HD下载地 ...
- Docker 删除&清理镜像
文章首发自个人网站:https://www.exception.site/docker/docker-delete-image 本文中,您将学习 Docker 如何删除及清理镜像? 一.通过标签删除镜 ...
- 286万QPS!腾讯云TDSQL打造数据库领域的“超音速战机”
Bloodhound SSC超音速汽车将陆地极限速度提升到1678公里/小时,号称陆地“超音速战斗机”.无独有偶,同样也在2017年,在英特尔®.腾讯金融云团队的共同见证下,腾讯云数据库TDSQL采用 ...
- Flink从入门到放弃(入门篇1)-Flink是什么
戳更多文章: 1-Flink入门 2-本地环境搭建&构建第一个Flink应用 3-DataSet API 4-DataSteam API 5-集群部署 6-分布式缓存 7-重启策略 8-Fli ...
- 博主新建Linux学习交流群,欢迎广大大神入驻~
一转眼2018已经过去,博主在博客园辛勤耕耘了1年多,也结识了很多志同道合的道友: 收获了“基”情满满的友谊的同时,也大大拓宽了自己的眼界~ 深深感到在漫漫的学习之路,需要有道友一同共勉和相互激励! ...
- 在CentOS上安装owncloud企业私有云过程
## ownclud是什么? ## >ownCloud 是一个开源免费专业的私有云存储项目,它能帮你快速在个人电脑或服务器上架设一套专属的私有云文件同步网盘,可以像 Dropbox 那样实现文件 ...
- 大数据---Ranger-1
背景:从软通出来,告别华为外包,离开H区,进入了一家搞大数据的创业公司,感觉周围都好陌生,记录下自己大数据的career! 2019-03-4新的征程-入职第一天: 一.办理入职手续 公司人比较少,没 ...
- 基础概念PHP-FPM、FastCGI和CGI
在搭建 LAMP/LNMP 服务器时,会经常遇到 PHP-FPM.FastCGI和CGI 这几个概念.如果对它们一知半解,很难搭建出高性能的服务器.接下来我们就以图形方式,解释这些概念之间的关系. 基 ...