题解 UVA1723 【Intervals】

呐,我们可以转化一下题面:

把某个正整数看作位置,选择这个正整数 即 此位置取 \(1\) ,不选表示此位置取 \(0\)

然后就得到了一个 \(01\) 串。

所以我们可以考虑维护一个前缀和,限制条件\(l-r\)至少有 \(k\) 个数即:

\[sum_r - sum_[l-1] >= k\]

但是实际上还有一个隐藏的限制条件:

\[sum_{i+1} - sum_i>=0\]

且:

\[sum_{i} - sum_{i+1}>=-1 \]

所以都要连边,然后跑最长路 \(QwQ\)


#include<bits/stdc++.h>
using namespace std;
int read() {
    char cc = getchar(); int cn = 0, flus = 1;
    while(cc < '0' || cc > '9') {  if( cc == '-' ) flus = -flus;  cc = getchar();  }
    while(cc >= '0' && cc <= '9')  cn = cn * 10 + cc - '0', cc = getchar();
    return cn * flus;
}
const int N = 5e5 + 5; 
#define rep( i, s, t ) for( register int i = s; i <= t; ++ i )
#define Next( i, x ) for( register int i = head[x]; i; i = e[i].next )
int n, maxn, dis[N], S, book[N], head[N], cnt, minn, vis[N];
struct E {
    int to, next, w;
} e[N * 2];
void init() {
    memset( head, 0, sizeof(head) ), cnt = 0;
}
void add( int x, int y, int z ) {
    e[++ cnt] = (E){ y, head[x], z }, head[x] = cnt;
}
void input() {
    n = read(); int x, y, z; minn = N;
    rep( i, 1, n ) {
        x = read(), y = read(), z = read(); 
        if( x > y ) swap( x, y );
        add( x - 1, y, z );
        maxn = max( maxn, y );
    }
    rep( i, 0, maxn ) add( i, i + 1, 0 ), add( i + 1, i, -1 );
}
queue< int> q;
void spfa( int x ) {
    while( !q.empty() ) q.pop();
    memset( dis, -63, sizeof(dis) ), memset( vis, 0, sizeof(vis) );
    memset( book, 0, sizeof(book) );
    dis[x] = 0, q.push(x);
    while( !q.empty() ) {
        int u = q.front(); q.pop(); 
        book[u] = 0, vis[u] = 1;
        Next( i, u ) {
            int v = e[i].to;
            if( dis[v] < dis[u] + e[i].w ) {
                if( !book[v] ) q.push(v), book[v] = 1;
                dis[v] = dis[u] + e[i].w;
            }
        }
    }
}
signed main()
{
    int T = read();
    while( T-- ) {
        init(), input();
        spfa(S), printf("%d\n", dis[maxn]);
        if(T) puts("");
    }
    return 0;
}
上一篇:道路翻新 (Revamping Trails, USACO 2009 Feb)


下一篇:2021-07-04