洛谷P3588 线段树优化建图

题目描述

给定一个长度为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],di,表示已知a[p[i]]=d[i],保证p[i]递增。接下来m行,每行一开始为三个正整数l[i],r[i],k[i](1<=l[i]

输出格式:

若无解,则输出NIE。否则第一行输出TAK,第二行输出n个正整数,依次输出序列a中每个数。

输入输出样例

输入样例#1: 复制

5 2 2

2 7

5 3

1 4 2 2 3

4 5 1 4

输出样例#1: 复制

TAK

6 7 1000000000 6 3

说明

给定一个长度为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个数大(严格大于,即没有等号)。

请任意构造出一组满足条件的方案,或者判断无解。

线段树建图优化模板,首先运用差分约束的思想,如果存在环则无解。因此可行解一定是个DAG,然后就是连边乱搞,发现强行乱搞是n^2,于是我们就要加优化。又发现一段连续的区间如果都连一条边十分浪费,又因为是连续的区间,想到用线段树去优化。

至于线段树中儿子连父亲还是父亲连儿子,视写法而定(我感觉挺玄乎的)。

#include
using namespace std;
const int Maxn=100000*log2(100000);
int n,s,m,v[Maxn],f[Maxn],d[Maxn],x[Maxn];
int tot,p[Maxn];
bool vst[Maxn];
struct Edge{
    int cnt,h[Maxn],w[Maxn*2],to[Maxn*2],next[Maxn*2];
    inline void add(int x,int y,int z){
        next[++cnt]=h[x];to[cnt]=y;w[cnt]=z;h[x]=cnt;++d[y];
    }
}e;
#define to e.to[p]
struct SegMent{
    struct tree{
        int ls,rs,l,r;
    }t[Maxn*2];int root;
    inline void link(int x,int l,int r,int y){
//		cout<r||t[x].r>1;
        if(l==r)return p[mid]=x,void();
        build(t[x].ls,l,mid),build(t[x].rs,mid+1,r);
        e.add(x,t[x].ls,0),e.add(x,t[x].rs,0);
    }
}seg;
inline bool topsort(){
    queueQ;
    for(int i=1;i<=tot;++i)f[i]=v[i]?v[i]:1e9;
    for(int i=1;i<=tot;++i)if(!d[i])Q.push(i);
    while(!Q.empty()){
        int x=Q.front();Q.pop();
        if(f[x]

 

你可能感兴趣的:(数据结构,线段树,拓扑排序)