51 NOD 1521 一维战舰(并查集)

来源:互联网 发布:linux环境变量的作用 编辑:程序博客网 时间:2024/05/01 03:54

题目链接:点击打开链接

思路: 倒着用并查集合并就行了,  一边合并一边统计,  当能放置的船数大于等于k就停止。

细节参见代码:

#include <cstdio>#include <cstring>#include <algorithm>#include <iostream>#include <string>#include <vector>#include <stack>#include <ctime>#include <bitset>#include <cstdlib>#include <cmath>#include <set>#include <list>#include <deque>#include <map>#include <queue>#define Max(a,b) ((a)>(b)?(a):(b))#define Min(a,b) ((a)<(b)?(a):(b))using namespace std;typedef long long ll;typedef long double ld;const double eps = 1e-6;const double PI = acos(-1);const int mod = 1000000000 + 7;const int INF = 0x3f3f3f3f;// & 0x7FFFFFFFconst int seed = 131;const ll INF64 = ll(1e18);const int maxn = 2e5 + 10;int T,n,m, p[maxn],k,a,x[maxn],cnt[maxn];bool vis[maxn];int _find(int x) { return p[x] == x ? x : p[x] = _find(p[x]); }int main() {    scanf("%d%d%d%d",&n, &k, &a, &m);    for(int i = 1; i <= m; i++) {        scanf("%d", &x[i]);        vis[x[i]] = 1;    }    int ans = -1, l = 0, tot = 0;    for(int i = 1; i <= n; i++) {        p[i] = i;        cnt[i] = 1;    }    for(int i = 1; i <= n; i++) {        if(vis[i]) {            for(int j = l+1; j < i-1; j++) {                int v1 = _find(j), v2 = _find(j+1);                if(v1 != v2) {                    p[v1] = v2;                    cnt[v2] += cnt[v1];                }            }            if(l+1 != i) {                int v1 = _find(l+1);                tot += (cnt[v1]+1) / (a+1);            }            l = i;        }    }    if(!vis[n]) {        for(int i = l+1; i < n; i++) {            int v1 = _find(i), v2 = _find(i+1);            if(v1 != v2) {                p[v1] = v2;                cnt[v2] += cnt[v1];            }        }        int v1 = _find(n);        tot += (cnt[v1]+1) / (a+1);    }    for(int i = m; i >= 1; i--) {        if(tot >= k) break;        if(x[i] == 1) {            if(vis[x[i]+1]) tot += 2 / (a+1);            else {                int l = _find(x[i]), r = _find(x[i]+1);                if(l != r) {                    p[l] = r;                    tot -= (cnt[r]+1)/(a+1);                    cnt[r] += cnt[l];                    tot += (cnt[r]+1)/(a+1);                }            }        }        else if(x[i] == n) {            if(vis[x[i]-1]) tot += 2 / (a+1);            else {                int l = _find(x[i]), r = _find(x[i]-1);                if(l != r) {                    p[l] = r;                    tot -= (cnt[r]+1)/(a+1);                    cnt[r] += cnt[l];                    tot += (cnt[r]+1)/(a+1);                }            }        }        else {            if(vis[x[i]-1] && vis[x[i]+1]) tot += 2 / (a+1);            else {                if(!vis[x[i]-1]) {                    int l = _find(x[i]-1), r = _find(x[i]);                    if(l != r) {                        p[l] = r;                        cnt[r] += cnt[l];                        tot -= (cnt[l]+1) / (a+1);                    }                }                if(!vis[x[i]+1]) {                    int l = _find(x[i]+1), r = _find(x[i]);                    if(l != r) {                        p[l] = r;                        cnt[r] += cnt[l];                        tot -= (cnt[l]+1) / (a+1);                    }                }                int r = _find(x[i]);                tot += (cnt[r]+1)/(a+1);            }        }        vis[x[i]] = 0;        ans = i;    }    printf("%d\n", ans);    return 0;}


0 0
原创粉丝点击