题目传送门

https://lydsy.com/JudgeOnline/problem.php?id=4383

题解

暴力的做法显然是把所有的条件拆分以后暴力建一条有向边表示小于关系。

因为不存在零环,所以随后可以用拓扑排序来解决。


考虑如何优化。

第一个优化比较显而易见,对于一个条件,新建一个虚点,连向所有给出的点。

第二个是,我们可以发现,给定这 \(k\) 个点以后,实际上需要建的边是从最多 \(k + 1\) 个区间中引出的,所以可以考虑线段树优化建图。

然后就可以和上面一样的,因为不存在零环,所以随后可以用拓扑排序来解决。

然后这样的时间复杂度是 \(O((m+\sum k)\log n)\)。


这似乎是我第一次写线段树优化建图呢~虽然一年前就已经学过了,但是一直没写过。

#include<bits/stdc++.h>

#define fec(i, x, y) (int i = head[x], y = g[i].to; i; i = g[i].ne, y = g[i].to)
#define dbg(...) fprintf(stderr, __VA_ARGS__)
#define File(x) freopen(#x".in", "r", stdin), freopen(#x".out", "w", stdout)
#define fi first
#define se second
#define pb push_back template<typename A, typename B> inline char smax(A &a, const B &b) {return a < b ? a = b, 1 : 0;}
template<typename A, typename B> inline char smin(A &a, const B &b) {return b < a ? a = b, 1 : 0;} typedef long long ll; typedef unsigned long long ull; typedef std::pair<int, int> pii; template<typename I> inline void read(I &x) {
int f = 0, c;
while (!isdigit(c = getchar())) c == '-' ? f = 1 : 0;
x = c & 15;
while (isdigit(c = getchar())) x = (x << 1) + (x << 3) + (c & 15);
f ? x = -x : 0;
} const int N = 100000 * 6 + 7;
const int M = 100000 * (4 + 3 + 17 + 17) + 7; #define lc o << 1
#define rc o << 1 | 1 int n, ns, m, nod;
int dp[N], nd[N], idg[N], pre[N], rel[N], tmp[N], q[N]; struct Edge { int to, ne, w; } g[M]; int head[N], tot;
inline void addedge(int x, int y, int z) { g[++tot].to = y, g[tot].w = z, g[tot].ne = head[x], head[x] = tot; }
inline void adde(int x, int y, int z) { addedge(x, y, z), addedge(y, x, z); } inline void add_e(int x, int y, int z) { ++idg[y], addedge(x, y, z); } inline void build(int o, int L, int R) {
if (L == R) return (void)(rel[L] = o, pre[o] = L);
int M = (L + R) >> 1;
add_e(lc, o, 0), build(lc, L, M);
add_e(rc, o, 0), build(rc, M + 1, R);
}
inline void addi(int o, int L, int R, int l, int r, int x) {
// dbg("o = %d, L = %d, R = %d, l = %d, r = %d, x = %d\n", o, L, R, l, r, x);
if (l <= L && R <= r) return add_e(o, x, 1);
int M = (L + R) >> 1;
if (l <= M) addi(lc, L, M, l, r, x);
if (r > M) addi(rc, M + 1, R, l, r, x);
} inline void work() {
int hd = 0, tl = 0;
for (int i = 1; i <= nod; ++i) if (idg[i] == 0) q[++tl] = i, smax(dp[i], 1);
while (hd < tl) {
int x = q[++hd];
// if (dp[x] >= n) dbg("******* x = %d, dp[x] = %d, nd[x] = %d\n", x, dp[x], nd[x]);
if (nd[x]) {
if (dp[x] > nd[x]) {
puts("NIE");
return;
} else dp[x] = nd[x];
}
for fec(i, x, y) {
smax(dp[y], dp[x] + g[i].w);
if (!--idg[y]) q[++tl] = y;
}
}
for (int i = 1; i <= n; ++i) if (!dp[rel[i]] || dp[rel[i]] > 1e9) {
puts("NIE");
return;
}
puts("TAK");
for (int i = 1; i <= n; ++i) printf("%d%c", dp[rel[i]], " \n"[i == n]);
} inline void init() {
read(n), read(ns), read(m);
int x, y;
build(1, 1, n);
nod = n << 2;
for (int i = 1; i <= ns; ++i) read(x), read(y), dp[rel[x]] = nd[rel[x]] = y;
for (int i = 1; i <= m; ++i) {
int l, r, k;
read(l), read(r), read(k);
++nod;
for (int i = 1; i <= k; ++i) {
read(tmp[i]);
add_e(nod, rel[tmp[i]], 0);
if (i == 1) tmp[i] > l ? addi(1, 1, n, l, tmp[i] - 1, nod) : (void)0;
else tmp[i] - tmp[i - 1] > 1 ? addi(1, 1, n, tmp[i - 1] + 1, tmp[i] - 1, nod) : (void)0;
}
if (tmp[k] != r) addi(1, 1, n, tmp[k] + 1, r, nod);
}
} int main() {
#ifdef hzhkk
freopen("hkk.in", "r", stdin);
#endif
init();
work();
fclose(stdin), fclose(stdout);
return 0;
}

最新文章

  1. idea导入maven项目,web browser远程单步调试
  2. C# 操作鼠标移动到指定的屏幕位置方法
  3. [WinAPI] API 7 [判断光驱内是否有光盘]
  4. nginx源码学习----内存池
  5. 从客户端中检测到有潜在危险的Request.Form值 的解决方法
  6. unity android 集成指南
  7. easyui源码翻译1.32--EasyLoader(简单加载)
  8. [置顶] 我的Android进阶之旅------&gt;介绍一款集录制与剪辑为一体的屏幕GIF 动画制作工具 GifCam
  9. C++是跨平台的语言
  10. “百度杯”CTF比赛 2017 二月场 爆破-3
  11. windows蜜汁调音
  12. 1001 害死人不偿命的(3n+1)猜想 (15 分)
  13. 关于表单----html杂记
  14. python简说(二十)操作excel
  15. webpack优化记录
  16. React技术栈梳理
  17. 【linux】linux查看资源任务管理器,使用top命令 + 查看java进程下的线程数量【两种方式】
  18. commons.httpclient-3.X.jar 和 httpclient-4.x.jar是个什么关系?
  19. Android学习整理之Activity篇
  20. Spring MVC深入讲解

热门文章

  1. React Native商城项目实战01 - 初始化设置
  2. 关于加快INSERT语句执行速度和HINT /*+ append */及/*+ append nologging */的使用
  3. (转)使用NMAP工具扫描端口
  4. Java面试题集(116-135)
  5. Java面试题集(86-115)
  6. cocos2dx基础篇(14) 滚动视图CCScrollView
  7. C#新特性span 和 Tuple
  8. 【Qt开发】【VS开发】【Linux开发】OpenCV、Qt-MinGw、Qt-msvc、VS2010、VS2015、Ubuntu Linux、ARM Linux中几个特别容易混淆的内容
  9. linux 系统目录权限
  10. Java实验3与第五周总结