题意

有一个\(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的更多相关文章

  1. P3588 [POI2015]PUS(拓扑排序+线段树)

    P3588 [POI2015]PUS 对于每个$(l,r,k)$,将$k$个位置向剩下$r-l-k+1$个位置连边,边权为$1$,这样就保证$k$个位置比剩下的大 先给所有位置填$1e9$保证最优 然 ...

  2. P3588 【[POI2015]PUS】(线段树优化建边)

    P3588 [[POI2015]PUS] 终于有个能让我一遍过的题了,写篇题解纪念一下 给定长度为n的序列和其中部分已知的数,还有m个大小关系:区间\([l,r]\)中,有k个给定的数比剩下的\(r- ...

  3. [POI2015]PUS

    嘟嘟嘟 这题只要往正确的方面想,就很简单. 首先,这是一道图论题! 想到这,这题就简单了.对于两个数\(i\)和\(j\),如果\(i\)比\(j\)大,就从\(i\)向\(j\)连边.然后如果图中存 ...

  4. 洛谷P3588 [POI2015]PUS

    题面 sol:说了是线段树优化建图的模板... 就是把一整个区间的点连到一个点上,然后用那个点来连需要连一整个区间的点就可以了,就把边的条数优化成n*log(n)了 #include <queu ...

  5. 洛谷P3588 [POI2015]PUS(线段树优化建图)

    题面 传送门 题解 先考虑暴力怎么做,我们把所有\(r-l+1-k\)中的点向\(x\)连有向边,表示\(x\)必须比它们大,那么如果这张图有环显然就无解了,否则的话我们跑一个多源最短路,每个点的\( ...

  6. P3588 [POI2015]PUS

    好题 思路:线段树优化建图+拓扑DP or 差分约束(都差不多): 提交:3次 错因:眼瞎没看题,Inf写的0x3f3f3f3f 题解: 类似差分约束的模型,\(a<b\rightarrow a ...

  7. [POI2015]PUS [线段树优化建图]

    problem 线段树优化建图,拓扑,没了. #include <bits/stdc++.h> #define ls(x) ch[x][0] #define rs(x) ch[x][1] ...

  8. POI2015 解题报告

    由于博主没有BZOJ权限号, 是在洛咕做的题~ 完成了13题(虽然有一半难题都是看题解的QAQ)剩下的题咕咕咕~~ Luogu3585 [POI2015]PIE Solution 模拟, 按顺序搜索, ...

  9. Luogu P3783 [SDOI2017]天才黑客

    题目大意 一道码量直逼猪国杀的图论+数据结构题.我猪国杀也就一百来行 首先我们要看懂鬼畜的题意,发现其实就是在一个带权有向图上,每条边有一个字符串信息.让你找一个点出发到其它点的最短路径.听起来很简单 ...

随机推荐

  1. 使用gulp构建微信小程序工作流

    前言 刚入门微信小程序的时候,一切都基于微信web开发者工具,没有使用其他框架,也没有工程化的概念.当时做的项目都比较简单,单单用微信web开发者工具倒也得心应手.学了些东西后,就按捺不住地想跳出原生 ...

  2. 分享基于EF6、Unitwork、Autofac的Repository模式设计

    目录 分享基于EF6.Unitwork.Autofac的Repository模式设计 一.实现的思路和结构图 二.Repository设计具体的实现代码 三.Repository设计的具体的使用 四. ...

  3. 题解 P5016 【龙虎斗】

    首先祝各位大佬noip有个好成绩吧 当时比赛有个大数据,蒟蒻我暴力居然过了,好激动 这题一定要注意开long long (那个大数据就是我开long long才过的) 还有刚开始应设置答案为m(见解析 ...

  4. Hive调优策略

    Hive调优策略 Fetch抓取 Fetch抓取是指,Hive中对某些情况的查询可以不必使用MapReduce计算. 例如:select * from employee:在这种情况下,Hive可以简单 ...

  5. RabbitMQ延迟消息的延迟极限是多少?

    之前在写Spring Cloud Stream专题内容的时候,特地介绍了一下如何使用RabbitMQ的延迟消息来实现定时任务.最近正好因为开发碰到了使用过程中发现,延迟消息没有效果,消息直接就被消费了 ...

  6. 一位 iOS 大牛的 BAT面试心得与经验总结,送给正在迷茫 的你!

    前言: 目前形势,参加到 iOS 队伍的人是越来越多,可以说是已经达到了供过于求的地步了. 今年,找过工作人可能会更深刻地体会到今年的就业形势不容乐观,之前实习的时候就想着写一篇面经,后来忙就给忘了, ...

  7. spring boot入门篇

    Spring Boot[快速入门]   Spring Boot 概述 Build Anything with Spring Boot:Spring Boot is the starting point ...

  8. PIVOT内置函数实现行转列

    PIVOT用于将列值旋转为列名(即行转列),PIVOT的一般语法是:PIVOT(聚合函数(列) FOR 列 in (…) )AS P 完整语法: table_source PIVOT( 聚合函数(va ...

  9. 蘑菇街工程师常用的Linux命令!

    一.查看日志 线上出现了问题,登上线上的机器查日志是非常常见的操作了.我第一次登上线上机器查日志的时候,我还只记得以下的几个命令(假设现在我们的日志文件叫做service.log): cat serv ...

  10. windows server2008下搭建ftp服务

    在工作中不光使用linux系统下的ftp服务,也得使用windows下的,今天领导让我做一个,踩了很多坑,终于是做完了,重现下过程,我们就来一步一步搭建我们的windows下的ftp服务器: 1.环境 ...