Description

给定一个长度为n的正整数序列a,每个数都在1到10^9范围内,告诉你其中s个数,并给出m条信息,每条信息包含三个数l,r,k以及接下来k个正整数,表示a[l],a[l+1],...,a[r-1],a[r]里这k个位置的数中的任意一个都比任意一个剩下的r-l+1-k个数大(严格大于,即没有等号)。
请任意构造出一组满足条件的方案,或者判断无解。
输入格式:
第一行包含三个正整数n,s,m(1<=s<=n<=100000,1<=m<=200000)。
接下来s行,每行包含两个正整数p[i],d[i](1<=p[i]<=n,1<=d[i]<=10^9),表示已知a[p[i]]=d[i],保证p[i]递增。
接下来m行,每行一开始为三个正整数l[i],r[i],k[i](1<=l[i]<r[i]<=n,1<=k[i]<=r[i]-l[i]),接下来k[i]个正整数x[1],x[2],...,x[k[i]](l[i]<=x[1]<x[2]<...<x[k[i]]<=r[i]),表示这k[i]个数中的任意一个都比任意一个剩下的r[i]-l[i]+1-k[i]个数大。Σk <= 300,000

Solution

本题的思路是:假如x比y大,则连一条边x->y。

由于这里的是有k个数是比其他在某个范围内的数要大并且k还有个范围,建图的过程我们考虑用线段树优化。

针对每一组x新建一个节点now,将所有的x[i]连过来,再由now出发,按照[l,r]被不同的x[1]-x[k[i]]分为的若干区间,去找线段树上的节点连边。

接下来按照拓扑序dp。假如点x是被确定为c的,然而递推过来却发现dp[x]比c还小那就肯定无解了(我们在dp的时候使dp[x]会尽量大)。

设当前队首节点为u,如果u不是线段树上的点也不是后来新建的节点now之一,则要求它的所有转移为dp[u]-1。反之转移为dp[u]即可。

这道题我场上想出来这么搞了但出于某种认为它可能会MLE的心理默默遁了。。

Code

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<cmath>
using namespace std;
int n,s,m;
int num[],p,d;
bool _is[],_sure[]; struct node{int y,nxt;}g[];int h[],tot=;int In[];
void add(int x,int y)
{ g[++tot]=node{y,h[x]};h[x]=tot;In[y]++;}
struct Seg_tree
{ int lc[],rc[],rt,cnt;
void build(int &k,int l,int r)
{
k=++cnt;
if (l==r) { add(k,l);return;}
int mid=(l+r)/;
build(lc[k],l,mid);build(rc[k],mid+,r);
add(k,lc[k]);add(k,rc[k]);
}
void link(int k,int l,int r,int p,int askx,int asky)
{
if (askx<=l&&r<=asky) {add(p,k);return;}
int mid=(l+r)/;
if (askx<=mid) link(lc[k],l,mid,p,askx,asky);
if (asky>mid) link(rc[k],mid+,r,p,askx,asky);
}
}Seg;
queue<int>q;
int x,y,js;
void bfs()
{
for (int i=;i<=Seg.cnt;i++) if (!In[i]) q.push(i); while (!q.empty())
{
x=q.front();q.pop();
if (!_is[x]) num[x]=,_is[x]=;
js=x<=n?num[x]:num[x]+;
for (int i=h[x];i;i=g[i].nxt)
{
In[y=g[i].y]--;
if (!In[y]) q.push(y);
if (!_sure[y])
{
if (!_is[y]) num[y]=js-,_is[y]=;
else num[y]=min(js-,num[y]);
} else if (_sure[y]&&num[y]>=js) {printf("NIE");exit();}
}
}
}
int l,r,k,_k[];
int main()
{
scanf("%d%d%d",&n,&s,&m);
Seg.cnt=n;
Seg.build(Seg.rt,,n);
for (int i=;i<=s;i++) {scanf("%d%d",&p,&d);num[p]=d;_is[p]=_sure[p]=;} for (int i=;i<=m;i++)
{
scanf("%d%d%d",&l,&r,&k);
int now=++Seg.cnt;
for (int j=;j<=k;j++)
{
scanf("%d",&_k[j]);add(_k[j],now);
}
if (_k[]>l) Seg.link(Seg.rt,,n,now,l,_k[]-);
if (_k[k]<r) Seg.link(Seg.rt,,n,now,_k[k]+,r);
for (int j=;j<k;j++)
if (_k[j+]-_k[j]>) Seg.link(Seg.rt,,n,now,_k[j]+,_k[j+]-);
}
bfs();
for (int i=;i<=n;i++) if (num[i]<) {printf("NIE");return ;}
//for (int i=1;i<=n;i++) if (!_is[i]) {printf("NIE");return 0;}
printf("TAK\n");
for (int i=;i<=n;i++) printf("%d ",num[i]);
}

[BZOJ4383][POI2015] Pustynia-[线段树+dp+拓扑排序]的更多相关文章

  1. BZOJ4383 [POI2015]Pustynia[线段树优化建边+拓扑排序+差分约束]

    收获挺大的一道题. 这里的限制大小可以做差分约束,从$y\to x$连$1$,表示$y\le x-1$即$y<x$,然后跑最长路求解. 但是,如果这样每次$k+1$个小区间每个点都向$k$个断点 ...

  2. 【bzoj4383】[POI2015]Pustynia 线段树优化建图+差分约束系统+拓扑排序

    题目描述 给定一个长度为n的正整数序列a,每个数都在1到10^9范围内,告诉你其中s个数,并给出m条信息,每条信息包含三个数l,r,k以及接下来k个正整数,表示a[l],a[l+1],...,a[r- ...

  3. 【BZOJ4383】[POI2015]Pustynia 线段树优化建图

    [BZOJ4383][POI2015]Pustynia Description 给定一个长度为n的正整数序列a,每个数都在1到10^9范围内,告诉你其中s个数,并给出m条信息,每条信息包含三个数l,r ...

  4. AGC001 F - Wide Swap【线段树+堆+拓扑排序】

    给出的模型很难搞,所以转换一下,记p[i]为i这个数的位置,然后相邻两个p值差>k的能交换,发现使原问题字典序最小也需要使这里的字典序最小 注意到p值差<=k的前后顺序一定不変,那么可以n ...

  5. AtCoder AGC001F Wide Swap (线段树、拓扑排序)

    题目链接: https://atcoder.jp/contests/agc001/tasks/agc001_f 题解: 先变成排列的逆,要求\(1\)的位置最小,其次\(2\)的位置最小,依次排下去( ...

  6. BZOJ_4383_[POI2015]Pustynia_线段树优化建图+拓扑排序

    BZOJ_4383_[POI2015]Pustynia_线段树优化建图+拓扑排序 Description 给定一个长度为n的正整数序列a,每个数都在1到10^9范围内,告诉你其中s个数,并给出m条信息 ...

  7. Tsinsen A1219. 采矿(陈许旻) (树链剖分,线段树 + DP)

    [题目链接] http://www.tsinsen.com/A1219 [题意] 给定一棵树,a[u][i]代表u结点分配i人的收益,可以随时改变a[u],查询(u,v)代表在u子树的所有节点,在u- ...

  8. HDU 3016 Man Down (线段树+dp)

    HDU 3016 Man Down (线段树+dp) Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Ja ...

  9. BZOJ_3747_[POI2015]Kinoman_线段树

    BZOJ_3747_[POI2015]Kinoman_线段树 Description 共有m部电影,编号为1~m,第i部电影的好看值为w[i]. 在n天之中(从1~n编号)每天会放映一部电影,第i天放 ...

随机推荐

  1. Python的优雅写法

    枚举 之前我们这样操作:           Python   1 2 3 4 i = 0 for item in iterable:     print i, item     i += 1 现在我 ...

  2. angularJs的工具方法1

    一.angular.bind();   改this指向 <!DOCTYPE HTML> <html ng-app> <head> <meta http-equ ...

  3. domain是什么

    一:domain表达式 domain表达式:通常用来筛选数据记录.它们使用特殊的语法,以便于Odoo ORM 将它们解析后生成对应的SQL WHERE数据库筛选语句. 二:domain的写法 doma ...

  4. 进入WinRe(windows恢复环境)

    放个预览图: 方法汇总: 1. 2 . +Shift  3 ”shutdown /r /o“ 或 "bootim" 4 5 启动中强制关闭3次以上 6 狂按F8 (不同的电脑操作不 ...

  5. HTML5 FormData对象

    利用FormData对象,你可以使用一系列的键值对来模拟一个完整的表单,然后使用XMLHttpRequest发送这个"表单". 创建一个FormData对象 你可以先创建一个空的F ...

  6. Spring(六)之自动装配

    一.自动装配模型 下面是自动连接模式,可以用来指示Spring容器使用自动连接进行依赖注入.您可以使用元素的autowire属性为bean定义指定autowire模式. 可以使用 byType 或者  ...

  7. 3.C++和C混合编程

    最近经常看到头文件中有 #ifdef __cplusplus extern "C" { #endif ....... #ifdef __cplusplus } #endif 这样的 ...

  8. fiddler常用功能一

    fiddler备忘,好久不用,有些步骤忘记了 1.本机pc,目前ie和chrome都可以直接抓取,但是搜狗浏览器暂时抓不到 2.手机端抓包 (1)设置下代理:fiddler客户端查看下端口,然后在手机 ...

  9. PHP去重可用

    //国外 $arr6 = array_merge($arr2,$arr4); $arr8 = array(); $arr10 = array(); foreach($arr6 as $k6=> ...

  10. Office365学习笔记—Lookup类型加载条目过多解决方案

    1,随着接触的项目越来越多,遇到的各种奇葩的问题也越来越多,不得不说,SharePoint是个好东西,提高了开发效率,简化了很多基础的功能.但是令人头疼的问题是,当你想做个稍微复杂点的功能,就不得不研 ...