NOIP模拟5

改题速度被全班大佬甩下三条街的大号蒟蒻还不赶紧找个地缝钻进去写个毛线的题解啊,于是下文好多截图。。

今天的题解真的好好哦!!!我再也没有见过更完美的题解了!!!

A. 战争

记录一下我改了一下午上限是TLE 38分……

code

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
const int maxn = 1e5 + 3;
const int inf = 0x3f3f3f3f;

int n, p, k, k1, k2, mem[maxn], siz[maxn], hv[maxn], jh[maxn], c[maxn];
int cs, dx, res, drt[maxn], ans;
bool vis[maxn], ext[maxn], yyg[maxn], del[maxn];
vector<int> vec;
int w[maxn], comp;

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 << 1) + (x << 3) + (ch^48);
        ch = getchar();
    }
    return x * f;
}

struct node 
{
    int u, v;
}a[maxn], b[maxn];

void get_mark(int num)
{
    fill(drt+1, drt+p+1, 0);
    fill(del+1, del+n+1, 0);
    for(int i=1; i<=k1; i++)
    {
        if(num & (1<<i-1)) 
        {
            if(!del[a[i].u]) del[a[i].u] = 1, drt[c[a[i].u]]++;
        }
        else 
        {
            if(!del[a[i].v]) del[a[i].v] = 1, drt[c[a[i].v]]++;
        }
    }
    comp = 0;
    for(int i=1; i<=p; i++)
    {
        if(siz[i] == drt[i]) comp++;
    }
}

void get_ans(int num)
{
    fill(mem+1, mem+p+1, 0);
    fill(vis+1, vis+n+1, 0);
    fill(ext+1, ext+p+1, 0);
    fill(w+1, w+p+1, 0);
    cs = 0; dx = 0; res = 0;
    for(int i=1; i<=k2; i++)
    {
        if(num & (1<<i-1))
        {
            if(del[b[i].u] || del[b[i].v]) return;
            if(!vis[b[i].u]) vis[b[i].u] = 1, hv[++cs] = b[i].u, mem[c[b[i].u]]++;
            if(!vis[b[i].v]) vis[b[i].v] = 1, hv[++cs] = b[i].v, mem[c[b[i].v]]++;
            if(!ext[c[b[i].u]]) ext[c[b[i].u]] = 1, jh[++dx] = c[b[i].u];
            if(!ext[c[b[i].v]]) ext[c[b[i].v]] = 1, jh[++dx] = c[b[i].v];
            w[c[b[i].u]]++;
        }
    }
    for(int i=1; i<=dx; i++)
    {
        if(w[jh[i]] + w[jh[i]] != mem[jh[i]] * (mem[jh[i]]-1)) return;
    }
    res = p - comp - dx;
    for(int i=1; i<=dx; i++) res += mem[jh[i]];
    if(res > vec.size())
    {
        ans = res; vec.clear();
        for(int i=1; i<=cs; i++) vec.push_back(hv[i]);
        fill(yyg+1, yyg+p+1, 0);
        for(int i=1; i<=n; i++)
        {
            if(del[i] || vis[i] || yyg[c[i]] || ext[c[i]]) continue;
            vec.push_back(i); yyg[c[i]] = 1;
        }
    }
}

int main()
{
    freopen("war.in", "r", stdin);
    freopen("war.out", "w", stdout);
    
    p = read(), n = read();
    for(int i=1; i<=n; i++)
    {
        c[i] = read(); siz[c[i]]++;
    }
    k = read();
    for(int i=1; i<=k; i++)
    {
        int u = read(), v = read();
        if(c[u] != c[v])
        {
            k1++; a[k1] = (node){u, v};
        }
        else 
        {
            k2++; b[k2] = (node){u, v};
        }
    }
    int mx1 = 1 << k1, mx2 = 1 << k2;
    for(int i=0; i<mx1; i++)
    {
        get_mark(i);
        for(int j=0; j<mx2; j++)
        {
            get_ans(j);
        }
    }
    printf("%d\n", (int)vec.size());
    for(int x : vec) printf("%d ", x);
    printf("\n");

    return 0;
}

然后就鹤了……

并且懒懒地截个图:

code
 //又鹤了
#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
const int maxn = 1e5 + 3;
const int inf = 0x3f3f3f3f;

int n, p, ans, sum, k, c[maxn], siz[maxn], epty, state, tmp, cnt;
int delcnt[maxn], vcov[maxn], ecov[maxn];
int deltag[maxn], addtag[maxn], vis[maxn];

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 << 1) + (x << 3) + (ch^48);
        ch = getchar();
    }
    return x * f;
}

struct que 
{
    int u, v, op;
    bool operator < (const que &T) const 
    {
        return op < T.op;
    }
}q[maxn];

void dfs(int r)
{
    if(r > k)
    {
        if(ans<sum+p-cnt-epty) 
        {
            ans = sum+p-cnt-epty; state = tmp;
        }
        return;
    }
    if(q[r].op == 0)
    {
        int u = q[r].u, v = q[r].v;

        if(deltag[u] == 0)
        {
            delcnt[c[u]]++;
            if(delcnt[c[u]] == siz[c[u]]) epty++;
        }
        deltag[u]++;
        dfs(r+1);
        deltag[u]--;
        if(deltag[u] == 0)
        {
            if(delcnt[c[u]] == siz[c[u]]) epty--;
            delcnt[c[u]]--;
        }

        if(deltag[v] == 0)
        {
            delcnt[c[v]]++;
            if(delcnt[c[v]] == siz[c[v]]) epty++;
        }
        deltag[v]++;
        tmp ^= (1 << r);
        dfs(r+1);
        deltag[v]--;
        if(deltag[v] == 0)
        {
            if(delcnt[c[v]] == siz[c[v]]) epty--;
            delcnt[c[v]]--;
        }
        tmp ^= (1 << r);
    }
    else 
    {
        int u = q[r].u, v = q[r].v;
        dfs(r+1);
        if(deltag[u] || deltag[v]) return;

        tmp ^= (1 << r);
        if(vcov[c[u]] && ecov[c[u]] == (ll)vcov[c[u]]*(vcov[c[u]]-1)/2) sum -= vcov[c[u]], cnt--;
        if(addtag[u] == 0) vcov[c[u]]++;
        if(addtag[v] == 0) vcov[c[v]]++;
        ecov[c[u]]++;
        if(vcov[c[u]] && ecov[c[u]] == (ll)vcov[c[u]]*(vcov[c[u]]-1)/2) sum += vcov[c[u]], cnt++;
        addtag[u]++; addtag[v]++;
        dfs(r+1);
        addtag[u]--; addtag[v]--;
        if(vcov[c[u]] && ecov[c[u]] == (ll)vcov[c[u]]*(vcov[c[u]]-1)/2) sum -= vcov[c[u]], cnt--;
        ecov[c[u]]--;
        if(addtag[u] == 0) vcov[c[u]]--;
        if(addtag[v] == 0) vcov[c[v]]--;
        if(vcov[c[u]] && ecov[c[u]] == (ll)vcov[c[u]]*(vcov[c[u]]-1)/2) sum += vcov[c[u]], cnt++;
        tmp ^= (1 << r);
    }
}

void print(int state)
{
    fill(ecov+1, ecov+1+p, 0);
    fill(vcov+1, vcov+1+p, 0);
    fill(addtag+1, addtag+1+n, 0);
    fill(deltag+1, deltag+1+n, 0);
    fill(delcnt+1, delcnt+1+p, 0);
    for(int i=1; i<=k; i++)
    {
        int u = q[i].u, v = q[i].v, w = state & (1<<i);
        if(q[i].op == 0)
        {
            if(w == 0)
            {
                if(deltag[u] == 0) 
                {
                    delcnt[c[u]]++;
                }
                deltag[u]++;
            }
            else 
            {
                if(deltag[v] == 0)
                {
                    delcnt[c[v]]++;
                }
                deltag[v]++;
            }
        }
        else 
        {
            if(w == 0) continue;
            if(addtag[u] == 0) vcov[c[u]]++;
            if(addtag[v] == 0) vcov[c[v]]++;
            ecov[c[u]]++;
            addtag[u]++; addtag[v]++;
        }
    }
    for(int u=1; u<=n; u++)
    {
        if(deltag[u]) continue;
        if(vcov[c[u]] && ecov[c[u]] == (ll)vcov[c[u]]*(vcov[c[u]]-1)/2) 
        {
            if(addtag[u]) printf("%d ", u);
        }
        else 
        {
            if(vis[c[u]]) continue;
            printf("%d ", u);
            vis[c[u]] = 1;
        }
    }
}

int main()
{
    freopen("war.in", "r", stdin);
    freopen("war.out", "w", stdout);
    
    p = read(), n = read();
    for(int i=1; i<=n; i++)
    {
        c[i] = read(); siz[c[i]]++;
    }
    k = read();
    if(k == 0)
    {
        printf("%d\n", p);
        for(int i=1; i<=n; i++)
        {
            if(vis[c[i]]) continue;
            printf("%d ", i); vis[c[i]] = 1;
        }
        exit(0);
    }
    for(int i=1; i<=k; i++)
    {
        q[i].u = read(), q[i].v = read();
        if(c[q[i].u] == c[q[i].v]) q[i].op = 1;
    }
    sort(q+1, q+1+k);
    dfs(1);
    printf("%d\n", ans);
    print(state);

    return 0;
}

 

B. 肥胖

看官方题解就好了!形式是最大生成树因为不好走的就不走,从结束的状态开始,合并的时候考虑两边哪个是“终点”,set和remove什么的直接并查集。

code
 #include <bits/stdc++.h>

using namespace std;

typedef long long ll;
const int maxn = 1e5 + 3;
const ll inf = 0x3f3f3f3f3f3f3f3f;

int n, m, f[maxn];
ll total, ans[maxn], w[maxn];

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 << 1) + (x << 3) + (ch^48);
        ch = getchar();
    }
    return x * f;
}

struct edge 
{
    int u, v; ll w;
    bool operator < (const edge &T) const
    {
        return w > T.w;
    }
}e[maxn];

int find(int x) {return f[x] == x ? x : f[x] = find(f[x]);}

int main()
{
    freopen("fat.in", "r", stdin);
    freopen("fat.out", "w", stdout);
    
    n = read(), m = read();
    for(int i=1; i<=n; i++) w[i] = read(), total += w[i];
    for(int i=1; i<=n; i++) ans[i] = inf;
    for(int i=1; i<=n; i++) f[i] = i;
    for(int i=1; i<=m; i++)
    {
        e[i].u = read(), e[i].v = read(), e[i].w = read();
    }
    sort(e+1, e+1+m);
    int tot = 0;
    for(int i=1; i<=m; i++)
    {
        int u = find(e[i].u), v = find(e[i].v);
        if(u == v) continue;
        ans[u] = max(min(ans[u], e[i].w-(total-w[u])), min(ans[v], e[i].w-(total-w[v])));
        w[u] += w[v]; f[v] = u;
        tot++;
        if(tot == n - 1) break;
    }
    printf("%lld\n", ans[find(1)] > 0 ? ans[find(1)] : -1);

    return 0;
}

 

C. 分摊

针不戳——60 pts的n^2暴力调了一个晚上!

60 pts
 #include <bits/stdc++.h>

using namespace std;

typedef long long ll;
const int maxn = 3e5 + 3;
const int inf = 0x3f3f3f3f;

int n, v[maxn];
ll f[maxn], siz[maxn];
bool vis[maxn];

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 << 1) + (x << 3) + (ch^48);
        ch = getchar();
    }
    return x * f;
}

struct node 
{
    int nxt, to;
}e[maxn];
int head[maxn], len;

void add(int x, int y)
{
    e[++len].to = y; e[len].nxt = head[x];
    head[x] = len;
}

void dfs2(int u)
{
    siz[u] = v[u];
    for(int i=head[u]; i; i=e[i].nxt)
    {
        int v = e[i].to;
        dfs2(v);
        siz[u] += siz[v];
    }
}

void dfs1(int u)
{
    for(int i=head[u]; i; i=e[i].nxt)
    {
        int v = e[i].to;
        dfs1(v);
        vis[u] |= vis[v];
    }
}

void dfs(int u, int id)
{
    if(u == id) return;
    int lim = 0;
    for(int i=head[u]; i; i=e[i].nxt)
    {
        int v = e[i].to;
        if(vis[v]) {lim = v; break;}
    }
    dfs(lim, id);
    f[u] += f[lim];
    for(int i=head[u]; i; i=e[i].nxt)
    {
        int v = e[i].to;
        if(vis[v]) continue;
        else f[u] += min(siz[v], f[lim]);
    }
}

int main()
{
    freopen("share.in", "r", stdin);
    freopen("share.out", "w", stdout);
    
    n = read();
    for(int i=1; i<=n; i++)
    {
        int x = read(); v[i] = read();
        add(x, i);
    }
    dfs2(0);
    for(int i=1; i<=n; i++)
    {
        fill(f, f+1+n, 0);
        fill(vis, vis+1+n, 0);
        f[i] = siz[i];
        vis[i] = 1;
        dfs1(0);
        dfs(0, i);
        printf("%lld\n", f[0]);
        vis[i] = 0;
    }

    return 0;
}

 

posted @ 2022-11-23 16:46  Catherine_leah  阅读(49)  评论(0编辑  收藏  举报
/* */