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;
}
时光花火,水月星辰

浙公网安备 33010602011771号