luoguP3588_[POI2015]PUS
题意
有一个\(n\)个数的序列,已知其中的\(k\)个数,然后有\(m\)个信息,每个信息给出区间\([l,r]\),和\(k\)个数,表示区间\([l,r]\)中这\(k\)个数大于剩下的\(r-l+1-k\)个数,求出一个方案。
分析
- 抄做的第一题线段树优化建图的题目,很巧妙。
- 大小关系我们可以看成是一条有向边,由小数连向大数,而两数之差就是边权,最后跑一遍拓扑排序,从最小的值更新,判断是否有环或者数值超过范围即可。
- 对于每一个信息,如果将大的数和小的数暴力两两连边,显然不行。
- 第一个优化是在两个数集之间加一个虚点,小数连向虚点,虚点连向大数,就相当于两两连边了,不过这样还是不够。
- 第二个优化就是用线段树来优化建图,因为给定的\(k\)个数其实是将区间\([l,r]\)分成\(k+1\)个小区间,这些小数集合,其实并不需要一一连边,只需要整个区间连向虚点即可。
代码
#include <bits/stdc++.h>
using namespace std;
#define ls i<<1
#define rs i<<1|1
#define mid (l+r)/2
const int N=5e5+50;
const int INF=1e9;
struct Edge{
int v,w,next;
}e[N*10];
int cnt,head[N],ind[N];
int n,s,m,l,r,k,x,a[N];
void init(){
cnt=0;
memset(head,-1,sizeof(head));
}
void add(int u,int v,int w){
e[cnt]=Edge{v,w,head[u]};
head[u]=cnt++;
ind[v]++;
}
//记录每个线段树节点的实际编号(图论中的节点)
int pt[N],tot;
void build(int i,int l,int r){
if(l==r){
pt[i]=l;
return;
}
pt[i]=++tot;
build(ls,l,mid);
build(rs,mid+1,r);
add(pt[ls],pt[i],0);
add(pt[rs],pt[i],0);
}
//线段树区间[ql,qr]对应的节点连向x(图)
void link(int i,int l,int r,int ql,int qr,int x){
if(ql<=l && qr>=r){
add(pt[i],x,0);
return;
}
if(ql<=mid){
link(ls,l,mid,ql,qr,x);
}
if(qr>mid){
link(rs,mid+1,r,ql,qr,x);
}
}
int ans[N],vis[N];
bool topo(){
queue<int> q;
int c=0;
for(int i=1;i<=tot;i++){
if(!ind[i]){
q.push(i);
}
if(!ans[i]){
//还不确定的数
ans[i]=1;
}
}
while(!q.empty()){
int u=q.front();
q.pop();
c++;
for(int i=head[u];i!=-1;i=e[i].next){
int v=e[i].v;
int w=e[i].w;
ans[v]=max(ans[v],ans[u]+w);
if(a[v] && ans[v]>a[v]){
return false;
}
--ind[v];
if(!ind[v]){
q.push(v);
}
}
}
return c==tot;
}
int main(){
// freopen("in.txt","r",stdin);
scanf("%d%d%d",&n,&s,&m);
init();
//线段树n个叶子节点1-n,然后其他父节点就++tot
tot=n;
build(1,1,n);
for(int i=1;i<=s;i++){
scanf("%d%d",&k,&x);
a[k]=ans[k]=x;
}
//对于给定的k个数也就是集合S1,都大于等于[l,r]剩下的数S2,因此需要两两连边
//优化1 建立虚点,S2连向虚点,虚点连向S1
//优化2 S2都是一些连续区间,可以用线段树来优化建图,让线段树区间连向虚点
for(int i=1;i<=m;i++){
scanf("%d%d%d",&l,&r,&k);
tot++;
int p=l-1;
//k个数将区间分为k+1段,对应的线段树区间分别连向虚点
for(int j=1;j<=k;j++){
scanf("%d",&x);
//虚点连向S1
add(tot,x,1);
//连续区间连向虚点
if(x>p+1){
//和上一个点之间有一段连续区间
link(1,1,n,p+1,x-1,tot);
}
p=x;
}
if(x<r){
link(1,1,n,x+1,r,tot);
}
}
//拓扑排序求出方案
bool flag=topo();
if(!flag){
printf("NIE\n");
return 0;
}
for(int i=1;i<=n;i++){
if(ans[i]>INF){
printf("NIE\n");
return 0;
}
}
printf("TAK\n");
for(int i=1;i<=n;i++){
printf("%d%c",ans[i],i==n?'\n':' ');
}
return 0;
}
luoguP3588_[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- ...
- [POI2015]PUS
嘟嘟嘟 这题只要往正确的方面想,就很简单. 首先,这是一道图论题! 想到这,这题就简单了.对于两个数\(i\)和\(j\),如果\(i\)比\(j\)大,就从\(i\)向\(j\)连边.然后如果图中存 ...
- 洛谷P3588 [POI2015]PUS
题面 sol:说了是线段树优化建图的模板... 就是把一整个区间的点连到一个点上,然后用那个点来连需要连一整个区间的点就可以了,就把边的条数优化成n*log(n)了 #include <queu ...
- 洛谷P3588 [POI2015]PUS(线段树优化建图)
题面 传送门 题解 先考虑暴力怎么做,我们把所有\(r-l+1-k\)中的点向\(x\)连有向边,表示\(x\)必须比它们大,那么如果这张图有环显然就无解了,否则的话我们跑一个多源最短路,每个点的\( ...
- 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]天才黑客
题目大意 一道码量直逼猪国杀的图论+数据结构题.我猪国杀也就一百来行 首先我们要看懂鬼畜的题意,发现其实就是在一个带权有向图上,每条边有一个字符串信息.让你找一个点出发到其它点的最短路径.听起来很简单 ...
随机推荐
- 详叙BeanWrapper和PropertyDescriptor
每篇一句 千古以来要饭的没有要早饭的,知道为什么吗? 相关阅读 [小家Spring]聊聊Spring中的数据转换:Converter.ConversionService.TypeConverter.P ...
- 个人永久性免费-Excel催化剂功能第27波-Excel工作表设置快捷操作
Excel催化剂在完善了数据分析场景的插件需求后,决定再补充一些日常绝大多数Excel用户同样可以使用到的小功能,欢迎小白入场,在不违背太多Excel最佳实践的前提下,Excel催化剂乐意为广大Exc ...
- vijos P1848 记数问题
自答[119ms内存456.0 KiB] #include<iostream>using namespace std;int num = 0;void judge(int n, int x ...
- lnmp php使用命令行去备份数据库
<?php //备份数据库we8和foshan $time = date("Y-m-d",time()); $backtime = date("Y-m-d" ...
- Go语言圣经习题练习_1.5. 获取URL
练习 1.7: 函数调用io.Copy(dst, src)会从src中读取内容,并将读到的结果写入到dst中,使用这个函数替代掉例子中的ioutil.ReadAll来拷贝响应结构体到os.Stdout ...
- HTTP 400 Bad request 原因
我在使用httpclient 发送http请求时遇到问题,请求报 400 Bad request.网上都在说下面这两个原因 400 是 HTTP 的状态码,主要有两种形式: 1.bad request ...
- Win常用软件
本节只适合windows系统 VScode 下载 安装 双击安装 打开目录方式 右键文件夹->使用VSCode打开 命令行打开 code folder [dzlua@win10:~]$ ls a ...
- js获取手机系统语言
只需 navigator.language 就可以获取手机系统语言,要做国际化的童鞋可以看看 如图:(第一次是简体,第二次切换English),zh-CN,en-US是语言代码 更多语言代码,请查看h ...
- S2:java集合框架
Java集合就是一个容器.面向对象语言对事物的体现都是以对象的形式存在,所以为了方便对多个对象的操作,就对对象进行存储,集合就是存储对象最常用的一种方式.集合只用于存储对象,集合长度是可变的,集合可以 ...
- Tomcat 单(多)实例部署使用
一.前言 (一).概述 Tomcat 是由 Apache 开发的一个 Servlet 容器,实现了对 Servlet 和 JSP 的支持,并提供了作为Web服务器的一些特有功能,如Tomcat管理和控 ...