[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]天才黑客
题目大意 一道码量直逼猪国杀的图论+数据结构题.我猪国杀也就一百来行 首先我们要看懂鬼畜的题意,发现其实就是在一个带权有向图上,每条边有一个字符串信息.让你找一个点出发到其它点的最短路径.听起来很简单 ...
随机推荐
- 做了这么多年java开发,关于 Long 和 BigDecimal 的相等比较,你可不一定能准确回答下面 26 个问题
Java 里面的 == 和equals的坑是在是太多了,即使做了多年java开发的程序员也不一定就能准确说出 a == b 或 a.equals(b) 这样简单的问题的答案. 请看下面这26道关于Lo ...
- 新DevOps八荣八耻
昀哥 20181001以随时可扩容可缩容可重启可切换机房流量为荣,以不能迁移为耻. 以可配置为荣,以硬编码为耻. 以系统互备为荣,以系统单点为耻. 以交付时有监控报警为荣,以交付裸奔系统为耻. 以无状 ...
- 单例模式的优化之路(java)
1.概述 最近在优化公司以前老项目的代码时,发现有些类的代码频繁地创建和销毁对象,资源消耗比较严重.针对这些做了一些优化,改用单例模式,避免频繁的创建和销毁对象,说起单例模式,相信每个人都会写,接下来 ...
- 【自然语言处理篇】--Chatterbot聊天机器人
一.前述 ChatterBot是一个基于机器学习的聊天机器人引擎,构建在python上,主要特点是可以自可以从已有的对话中进行学(jiyi)习(pipei). 二.具体 1.安装 是的,安装超级简单, ...
- Spring Boot中通过CORS解决跨域问题
今天和小伙伴们来聊一聊通过CORS解决跨域问题. 同源策略 很多人对跨域有一种误解,以为这是前端的事,和后端没关系,其实不是这样的,说到跨域,就不得不说说浏览器的同源策略. 同源策略是由Netscap ...
- 一套代码小程序&Web&Native运行的探索01
前言 前面我们对微信小程序进行了研究:[微信小程序项目实践总结]30分钟从陌生到熟悉 并且用小程序翻写了之前一个demo:[组件化开发]前端进阶篇之如何编写可维护可升级的代码 之前一直在跟业务方打交道 ...
- 云计算OpenStack:云计算介绍及组件安装(一)--技术流ken
云计算介绍 当用户能够通过互联网方便的获取到计算.存储等服务时,我们比喻自己使用到了“云计算”,云计算并不能被称为是一种计算技术,而更像是一种服务模式.每个运维人员心里都有一个对云计算的理解,而最普遍 ...
- 一次 C# 查詢數據庫 算法優化的案例
最近有次在修改某段程式時,發現一段程式算法看起來簡單. 但背後因為多次查詢數據庫,導致效能問題. 這段程式主要是利用 EPPLUS 讀取 Excel 資料,檢查資料是否已存在數據庫中,若有就將已存在的 ...
- 学了两天 react,乱讲一下学习思路,顺便弄了一个脚手架
之前一直用 vue 做一些小项目,最近接触了一个项目是用 react 做前端,虽然本身是做后端开发的,但是前端还是要了解一点的. 现在的项目基本上都是前后端分离的,后端就先不提了.前端的框架也是层出不 ...
- tomcat部署项目后,war包是否可刪?war包存在必要性!
在tomcat中webapps目錄上傳war包后, 对war解压时候. war不能在tomcat运行时删除,否则会删除自动解压的工程. 你可以停止tomcat后删除war. 当你重新部署的时候,如果 ...