首页 > 代码库 > bzoj 4383: [POI2015]Pustynia

bzoj 4383: [POI2015]Pustynia

复习了一下线段树优化建图的姿势,在线段树上连边跑拓扑排序

这题竟然卡vector……丧病

 

#include <bits/stdc++.h>#define N 1810000using namespace std;int s, n, m;int pi[N], vis[N];int lt[N], nt[N], bi[N], ci[N];int lp[N], np[N], bp[N];int tl;int lb[N], rb[N], lc[N], rc[N];int out[N], intr[N];int Q[N], fr, bc;inline void build(int a, int b, int c){    nt[++ tl] = lt[a]; lt[a] = tl; bi[tl] = b; ci[tl] = c;    np[tl] = lp[b]; lp[b] = tl; bp[tl] = a; out[a] ++;    /*    bi[a].push_back(b);    bp[b].push_back(a);    ci[a].push_back(c);    */    //printf("%d %d %d\n", a, b, c);}int tot;void dfs_build(int t, int l, int r, int x){    if (l > r) return;    if (l <= lb[t] && rb[t] <= r) {build(x, t, 0); return;}    if (l <= rb[lc[t]]) dfs_build(lc[t], l, r, x);    if (r >= lb[rc[t]]) dfs_build(rc[t], l, r, x);}int build_tree(int l, int r){    int t = ++ tot;    lb[t] = l; rb[t] = r;    if (l != r)    {        lc[t] = build_tree(l, (l + r) / 2);         rc[t] = build_tree((l + r) / 2 + 1, r);        build(t, lc[t], 0);        build(t, rc[t], 0);    }    else intr[l] = t;    return t;}inline int read(){    int x=0,f=1;char ch=getchar();    while(ch<0||ch>9){if(ch==-)f=-1;ch=getchar();}    while(ch>=0&&ch<=9){x=x*10+ch-0;ch=getchar();}    return x*f;}int main(){    n = read(); s = read(); m = read();    build_tree(1, n);    for (int i = 1; i <= s; ++ i)    {        int p, d;        p = read(); d = read();        pi[intr[p]] = d;    }         //return 0;    for (int i = 1; i <= m; ++ i)    {        int l, r, k;        l = read(); r = read(); k = read();                 for (int j = 1, p = l - 1; j <= k + 1; ++ j)        {            int a;            if (j <= k)            {                a = read();                build(intr[a], tot + i, 1);            }            else a = r + 1;            if ((a - 1) - (p + 1) <= 10)            {                for (int q = p + 1; q < a; ++ q)                    build(tot + i, intr[q], 0);            }            else                 dfs_build(1, p + 1, a - 1, tot + i);            p = a;        }    }    for (int i = 1; i <= m + tot; ++ i)        if (!out[i]) Q[bc ++] = i;        while (fr != bc)    {        int hd = Q[fr ++]; vis[hd] = 1;        int mx = 1;        for (int i = lt[hd]; i; i = nt[i])            mx = max(mx, pi[bi[i]] + ci[i]);        if (!pi[hd])        {            if (mx > 1000000000)            {                puts("NIE");                return 0;            }            pi[hd] = mx;        }        else if (mx > pi[hd])        {            puts("NIE");            return 0;        }                for (int i = lp[hd]; i; i = np[i])        {            out[bp[i]] --;            if (!out[bp[i]])                Q[bc ++] = bp[i];        }    }    for (int i = 1; i <= m + tot; ++ i)        if (!vis[i]) {puts("NIE"); return 0;}    puts("TAK");    for (int i = 1; i <= n; ++ i) printf("%d ", pi[intr[i]]);}

话说是不是在主席树上也可以干一样的事情呢(手动斜眼

bzoj 4383: [POI2015]Pustynia