BZOJ4383 [POI2015]Pustynia[线段树优化建边+拓扑排序+差分约束]
收获挺大的一道题。
这里的限制大小可以做差分约束,从$y\to x$连$1$,表示$y\le x-1$即$y<x$,然后跑最长路求解。
但是,如果这样每次$k+1$个小区间每个点都向$k$个断点连边显然爆炸。。考虑优化建边。
发现这里是每个小区间各点连边,所以可以线段树优化,不过每个小区间都要向$k$个点连边还是爆炸,这时候,考虑一种类似于线段树建边里面区间向区间的连边方式:这一边的各个拆分的小区间向一个虚点连边,这个虚点再向另一个区间拆分的小区间连边,保证了边数=区间数=$\log$级别。那这里也类似,只要把$k+1$小段每一段的拆分区间全连上虚点,然后虚点连向$k$个点就行了,本质还是线段树建边的类比。由于保证了$\sum k$,所以边数在$\sum k\log n$级别。
然后,这样一张图是和原图等价的,这时我们要做一个差分约束的求解。不过,注意到,只要这里面出现了环,那肯定是正环(因为线段树图和原图等价,原图全是$1$边),肯定就无解。如果没有环,那么就是个DAG,这时我们并不用很蠢的跑spfa(因为容易被卡,比如说链),直接拓扑排序更新max就行了。最后注意一下不合法(超过$1e9$或超过原来给定值)就行了。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
#define mst(x) memset(x,0,sizeof x)
#define dbg(x) cerr << #x << " = " << x <<endl
#define dbg2(x,y) cerr<< #x <<" = "<< x <<" "<< #y <<" = "<< y <<endl
using namespace std;
typedef long long ll;
typedef double db;
typedef pair<int,int> pii;
template<typename T>inline T _min(T A,T B){return A<B?A:B;}
template<typename T>inline T _max(T A,T B){return A>B?A:B;}
template<typename T>inline char MIN(T&A,T B){return A>B?(A=B,):;}
template<typename T>inline char MAX(T&A,T B){return A<B?(A=B,):;}
template<typename T>inline void _swap(T&A,T&B){A^=B^=A^=B;}
template<typename T>inline T read(T&x){
x=;int f=;char c;while(!isdigit(c=getchar()))if(c=='-')f=;
while(isdigit(c))x=x*+(c&),c=getchar();return f?x=-x:x;
}
const int N=1e5+;
int org[N],val[N<<],deg[N<<];
int n,s,m,cnt,res;
struct thxorz{
int head[N<<],nxt[N*],to[N*],tot;
bool w[N*];
inline void add(int x,int y,int z){to[++tot]=y,nxt[tot]=head[x],head[x]=tot,w[tot]=z,++deg[y];}
}G;
struct SGT{
int id[N<<];
#define lc i<<1
#define rc i<<1|1
void build(int i,int L,int R){
if(L==R){id[i]=L;return;}
int mid=L+R>>;id[i]=++cnt;
build(lc,L,mid),build(rc,mid+,R);
G.add(id[lc],id[i],),G.add(id[rc],id[i],);
}
void update(int i,int L,int R,int ql,int qr){
if(ql<=L&&qr>=R){G.add(id[i],cnt,);return;}
int mid=L+R>>;
if(ql<=mid)update(lc,L,mid,ql,qr);
if(qr>mid)update(rc,mid+,R,ql,qr);
}
}T;
queue<int> q;
#define y G.to[j]
inline void topo(){
for(register int i=;i<=n;++i)if(!deg[i])q.push(i);//dbg(i);
while(!q.empty()){
int x=q.front();q.pop();++res;
for(register int j=G.head[x];j;j=G.nxt[j]){
MAX(val[y],val[x]+G.w[j]);//mistake
if(!(--deg[y]))q.push(y);
}
}
}
#undef y
int main(){//freopen("test.in","r",stdin);//freopen("test.ans","w",stdout);
cnt=read(n),read(s),read(m);
fill(val+,val+n+n+m+,);
for(register int i=,x;i<=s;++i)read(x),val[x]=read(org[x]);
T.build(,,n);
for(register int i=,l,r,k;i<=m;++i){
read(l),read(r),read(k);++cnt;
for(register int j=,x,las=l-;j<=k;++j,las=x){
read(x);G.add(cnt,x,);
if(las+<x)T.update(,,n,las+,x-);
if(j==k&&x<r)T.update(,,n,x+,r);
}
}
topo();
if(res<cnt){puts("NIE");return ;}
for(register int i=;i<=n;++i)if(val[i]>1e9||org[i]&&val[i]>org[i]){puts("NIE");return ;}
puts("TAK");
for(register int i=;i<=n;++i)printf("%d%c",val[i]," \n"[i==n]);
return ;
}
这题给了我一点启示。。
首先,区间连边,铁定是要线段树优化的。。只是有时候可能并不是那么显然,所以就要靠改造。。
然后,这个差分约束求解,并不是非要跑spfa的,如果原图是DAG,可以拓扑,这一点再拓展一下,就可以线性求全正权图的差分约束了,update了一下这篇。BZOJ2330 糖果[差分约束方案+spfa?/tarjan]
BZOJ4383 [POI2015]Pustynia[线段树优化建边+拓扑排序+差分约束]的更多相关文章
- BZOJ_4383_[POI2015]Pustynia_线段树优化建图+拓扑排序
BZOJ_4383_[POI2015]Pustynia_线段树优化建图+拓扑排序 Description 给定一个长度为n的正整数序列a,每个数都在1到10^9范围内,告诉你其中s个数,并给出m条信息 ...
- [POI2015][bzoj4383] Pustynia [线段树优化建图+拓扑排序]
题面 bzoj权限题传送门 luogu传送门 思路 首先,这个题目显然可以从所有小的点往大的连边,然后如果没环就一定可行,从起点(入读为0)开始构造就好了 但是问题来了,如果每个都连的话,本题中边数是 ...
- 【bzoj4383】[POI2015]Pustynia 线段树优化建图+差分约束系统+拓扑排序
题目描述 给定一个长度为n的正整数序列a,每个数都在1到10^9范围内,告诉你其中s个数,并给出m条信息,每条信息包含三个数l,r,k以及接下来k个正整数,表示a[l],a[l+1],...,a[r- ...
- 牛客多校第四场 J.Hash Function(线段树优化建图+拓扑排序)
题目传送门:https://www.nowcoder.com/acm/contest/142/J 题意:给一个hash table,求出字典序最小的插入序列,或者判断不合法. 分析: eg.对于序列{ ...
- [POI2015]PUS [线段树优化建图]
problem 线段树优化建图,拓扑,没了. #include <bits/stdc++.h> #define ls(x) ch[x][0] #define rs(x) ch[x][1] ...
- [bzoj5017][Snoi2017]炸弹 tarjan缩点+线段树优化建图+拓扑
5017: [Snoi2017]炸弹 Time Limit: 30 Sec Memory Limit: 512 MBSubmit: 608 Solved: 190[Submit][Status][ ...
- BZOJ 5496: [2019省队联测]字符串问题 (后缀数组+主席树优化建图+拓扑排序)
题意 略 分析 考场上写了暴力建图40分溜了-(结果只得了30分) 然后只要优化建边就行了 首先给出的支配关系无法优化,就直接A向它支配的B连边. 考虑B向以B作为前缀的所有A连边,做一遍后缀数组,两 ...
- 洛谷P3588 [POI2015]PUS(线段树优化建图)
题面 传送门 题解 先考虑暴力怎么做,我们把所有\(r-l+1-k\)中的点向\(x\)连有向边,表示\(x\)必须比它们大,那么如果这张图有环显然就无解了,否则的话我们跑一个多源最短路,每个点的\( ...
- bzoj4383 [POI2015]Pustynia 拓扑排序+差分约束+线段树优化建图
题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=4383 题解 暴力的做法显然是把所有的条件拆分以后暴力建一条有向边表示小于关系. 因为不存在零环 ...
随机推荐
- innodb事务锁的一些常见数据结构
lock_sys_t 整个innodb的锁系统管理结构体,定义在lock0lock.h中.在lock0lock.cc中有一个lock_sys_t的全局指针lock_sys, 由lock_sys_cre ...
- vue-cli3创建vue项目之vue.config.js配置
module.exports = { // 基本路径 publicPath: '/', // 输出文件目录 outputDir: 'dist', // eslint-loader 是否在保存的时候检查 ...
- iostream重载__int128
Normal (Naive)写法,用 string(char* ) std::ostream& operator <<(std::ostream&out,const __i ...
- split(".")不生效的问题
前言:今天用String的split(".")函数分割字符串,结果总是一个空的String数组: 解决:输入的regex是一个正则表达式,很多在正则表达式里面有特殊意义的比如 &q ...
- 【规律】A Rational Sequence
题目描述 An infinite full binary tree labeled by positive rational numbers is defi ned by:• The label of ...
- (转)如何真正实现由文档驱动的API设计?
前言 本文主要介绍了一种新的开发思路:通过反转开发顺序,直接从API文档中阅读代码.作者认为通过这种开发方式,你可以更清楚地知道文档表达出什么以及它应该如何实现. 如果单从API文档出发,由于信息量不 ...
- hdu 1068 最大子序列和变形,,,
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #d ...
- hdu 1269 入手强连通
思路待整理 #include<cstdio> #include<iostream> #include<cstring> #include<vector> ...
- 通过ADB调试安卓程序
ADB,即 Android Debug Bridge,它是Android开发/测试人员不可替代的强大工具. 1.下载ADB后,将以下四个文件放到某个文件夹下即可.因为打开Cmd默认路径是 C:\Use ...
- MongoDB的复合唯一索引
一 创建 JavaScript Shell db.room.ensureIndex({'floor':1,'num':1}) Spring Data @Data // lombok @Document ...