Portal

Description

给定一个长度为\(n(n\leq10^5)\)的正整数序列\(\{a_n\}\),每个数都在\([1,10^9]\)范围内,告诉你其中\(s\)个数,并给出\(m(m\leq2\times10^5)\)条信息。每条信息包含三个数\(L,R,k(Σk\leq 3\times10^5)\)以及\(k\)个正整数\(\{x_k\}\),表示\(a_L..a_R\)中,任意一个\(x\)均比剩下的\(R-L+1-k\)个数大(严格大于,即没有等号)。请任意构造出一组满足条件的方案,或者判断无解。

Solution

拓扑排序+线段树优化建图。

定义点权为\(val\);存在一条边权为\(w\)的边\((u,v)\)表示\(val[v]\geq val[u]+w\)。

首先考虑朴素的做法。建立\(n\)个点,\(val[i]\)表示\(a_i\)的值。对于每一条信息,新建一个点\(p\),\(val[p]\)表示\(min\{x_k\}\);剩下的数分别向\(p\)连一条边权为\(1\)的边(\(min\{x_k\}\)大于剩下的数),\(p\)向\(x_1..x_k\)分别连一条边权为\(0\)的边(\(x_i\)大于等于\(min\{x_k\}\))。初始时入度为\(0\)的点若没有值则令其\(val=1\),然后进行拓扑排序,如果成环或与初值冲突则无解。这样共有\(O(nm)\)条边。

考虑到边权为\(1\)的边的起点相当于\(k+1\)个区间,我们可以用线段树来优化建图。举例:\(n=8,a_3=7,a_5=4,a_7=2\),\([1,4]\)中最大的是\(\{2,3\}\),\([4,8]\)中是\(\{6\}\),\([1,8]\)中是\(\{2\}\)。



其中虚线边的权值为\(0\),实线边的权值为\(1\)。对于蓝线以上的点(线段树上的点),其\(val\)表示区间中的最大值;对于蓝线以下的点(条件所代表的点),其\(val\)表示\(min\{x_k\}\)。意义还是很明确的:例如边\(([3,4],\{2\})\)的权值为\(1\),表示\(min\{a_2\}>max\{3,4\}\)。同样机型拓扑排序并判断无解即可。至于边数...线段树上有\(2n\)条边,\(m\)条信息总共划分了\(m+Σk\)个区间,每个区间对应\(O(logn)\)条边,\(\{x_k\}\)共对应\(Σk\)条边;共计约\(2n+Σk+(m+Σk)logn\)条边。当然实际上要小很多,因为一条信息中所有区间的和是\([1,n]\),每个区间对应的边数远不足\(logn\)。算这么多干嘛直接开vector能过就行啊

Code

//[POI2015]Pustynia
#include <cstdio>
#include <queue>
#include <vector>
using namespace std;
inline char gc()
{
static char now[1<<16],*s,*t;
if(s==t) {t=(s=now)+fread(now,1,1<<16,stdin); if(s==t) return EOF;}
return *s++;
}
inline int read()
{
int x=0; char ch=gc();
while(ch<'0'||'9'<ch) ch=gc();
while('0'<=ch&&ch<='9') x=x*10+ch-'0',ch=gc();
return x;
}
inline int max(int x,int y) {return x>y?x:y;}
const int N=1e5+10;
int n,n1,m;
int cnt,rt,chL[N<<1],chR[N<<1];
const int N1=4e5+10;
int edCnt;
int val[N1],a[N1],in[N1],id[N];
vector< pair<int,bool> > son[N1];
inline void edAdd(int u,int v,bool w) {edCnt++; in[v]++; son[u].push_back(make_pair(v,w));}
void bldTr(int &p,int L0,int R0)
{
if(!p) p=++cnt;
if(L0==R0) {id[L0]=p; return;}
int mid=L0+R0>>1;
bldTr(chL[p],L0,mid),bldTr(chR[p],mid+1,R0);
edAdd(chL[p],p,0),edAdd(chR[p],p,0);
}
int optL,optR;
void trEdAdd(int p,int L0,int R0)
{
if(optL<=L0&&R0<=optR) {edAdd(p,cnt,1); return;}
int mid=L0+R0>>1;
if(optL<=mid) trEdAdd(chL[p],L0,mid);
if(mid<optR) trEdAdd(chR[p],mid+1,R0);
}
queue<int> Q;
int main()
{
n=read(),n1=read(),m=read();
bldTr(rt,1,n);
for(int i=1;i<=n1;i++) {int u=id[read()]; val[u]=a[u]=read();}
for(int i=1;i<=m;i++)
{
int L=read(),R=read(),k0=read();
cnt++; int pre=L;
while(k0--)
{
int x=read();
optL=pre,optR=x-1; if(optL<=optR) trEdAdd(rt,1,n);
pre=x+1; edAdd(cnt,id[x],0);
}
optL=pre,optR=R; if(optL<=optR) trEdAdd(rt,1,n);
}
for(int u=1;u<=cnt;u++) if(!in[u]) val[u]=max(1,a[u]),Q.push(u);
bool noAns=false;
while(!noAns&&!Q.empty())
{
int u=Q.front(); Q.pop();
if(a[u]&&val[u]>a[u]) {noAns=true; break;}
for(int i=0;i<son[u].size();i++)
{
int v=son[u][i].first,w=son[u][i].second;
val[v]=max(val[v],val[u]+w);
if(--in[v]==0) Q.push(v);
}
}
for(int u=1;u<=cnt&&!noAns;u++) if(in[u]||val[u]>1e9) noAns=true;
if(noAns) {puts("NIE"); return 0;}
puts("TAK");
for(int i=1;i<=n;i++) printf("%d ",val[id[i]]);
puts("");
return 0;
}

P.S.

每个数都在\([1,10^9]\)范围内! 意思是说如果你推出来有的数大于\(10^9\)就是无解,坑我半天...

洛谷P3588 - [POI2015]Pustynia的更多相关文章

  1. 洛谷P3588 [POI2015]PUS

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

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

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

  3. 洛谷P3582 [POI2015]KIN

    题目描述 共有\(m\)部电影,编号为\(1--m\),第\(i\)部电影的好看值为\(w[i]\).在\(n\)天之中(从\(1~n\)编号)每天会放映一部电影,第\(i\)天放映的是第\(f[i] ...

  4. BZOJ 4385 洛谷3594 POI2015 WIL-Wilcze doły

    [题解] 手残写错调了好久QAQ...... 洛谷的数据似乎比较水.. n个正整数!!这很重要 这道题是个类似two pointer的思想,外加一个单调队列维护当前区间内长度为d的子序列中元素之和的最 ...

  5. 洛谷 P3586 [POI2015]LOG

    P3586 [POI2015]LOG 题目描述 维护一个长度为n的序列,一开始都是0,支持以下两种操作:1.U k a 将序列中第k个数修改为a.2.Z c s 在这个序列上,每次选出c个正数,并将它 ...

  6. 洛谷 P3585 [POI2015]PIE

    P3585 [POI2015]PIE 题目描述 一张n*m的方格纸,有些格子需要印成黑色,剩下的格子需要保留白色.你有一个a*b的印章,有些格子是凸起(会沾上墨水)的.你需要判断能否用这个印章印出纸上 ...

  7. 洛谷P3586 [POI2015]LOG(贪心 权值线段树)

    题意 题目链接 Sol 显然整个序列的形态对询问没什么影响 设权值\(>=s\)的有\(k\)个. 我们可以让这些数每次都被选择 那么剩下的数,假设值为\(a_i\)次,则可以\(a_i\)次被 ...

  8. 洛谷P3585 [POI2015]PIE

    传送门 题目大意:有个n*m的格子图,要求'x'点要被染成黑色 有个a*b的印章,'x'是可以染色的印章上的点. 要求用印章去染色格子 (1)印章不可以旋转. (2)不能把墨水印到纸外面. (3)纸上 ...

  9. BZOJ 3747 洛谷 3582 [POI2015]Kinoman

    [题解] 扫描线+线段树. 我们记第i部电影上次出现的位置是$pre[i]$,我们从$1$到$n$扫描,每次区间$(pre[i],i]$加上第i部电影的贡献$w[f[i]]$,区间$[pre[pre[ ...

随机推荐

  1. Redis学习笔记(一)五种数据类型

    1.字符串(String) 基本操作:SET(设置).GET(获取).DEL(删除)其他操作传送门 root@localhost:~# redis-cli > set msg hello OK ...

  2. Android(java)学习笔记146:网页源码查看器(Handler消息机制)

    1.项目框架图: 2.首先是布局文件activity_main.xml: <LinearLayout xmlns:android="http://schemas.android.com ...

  3. js 获取当前URL信息

    document.location 这个对象包含了当前URL的信息 location.host 获取port号 location.hostname 设置或获取主机名称 location.href 设置 ...

  4. 多源最短路径 – Floyd-Warshall Algorithm

    介绍: 是解决任意两点间的最短路径的一种算法,可以正确处理有向图或负权(但不可存在负权回路)的最短路径问题,同时也被用于计算有向图的传递闭包. Floyd-Warshall算法的时间复杂度是O(N3) ...

  5. Java数据结构和算法(五)--希尔排序和快速排序

    在前面复习了三个简单排序Java数据结构和算法(三)--三大排序--冒泡.选择.插入排序,属于算法的基础,但是效率是偏低的,所以现在 学习高级排序 插入排序存在的问题: 插入排序在逻辑把数据分为两部分 ...

  6. C05 C语言字符串和数组

    目录 数组 字符串 数组 概念 数组是有序数据的集合. 数组中的每一个元素属于同一个数据类型. 通过数组名和下标唯一确定数组中的元素. 一维数组的定义 语法格式 数据类型   数组名[常量表达式] 例 ...

  7. OAuth授权之回调accessToken

    具体说明见新浪官方文档 http://open.weibo.com/wiki/Oauth2/access_token   具体实现 第一步 打开回调页面 // 宏定义client_id #define ...

  8. 关于HTML设置访问密码。

    如果你要设置访问密码恐怕要使用sublime_text了 废话不多,开始!!! 先把这些东西加上: <html> <script> 然后开始写代码: 先辨别密码登录正确的情况: ...

  9. python私有成员与公有成员(_和__)

    python并没有对私有成员提供严格的访问保护机制. 在定义类的成员时,如果成员名以两个下划线“__”或更多下划线开头而不以两个或更多下划线结束则表示是私有成员. 私有成员在类的外部不能直接访问,需要 ...

  10. 暴力解说之首次部署NGINX

    前言 本章基于Centos 7.x系统讲解 本章讲解下在项目上线部署的时候对NGINX的操作.有些童鞋在网上百度类似LNMP安装就跟着命令一条一条执行了,如果没报错还好,一旦报错就懵逼状态了.这是对自 ...