2020 省选模拟测试 Round #8 solution (20/02/07)

Posted rensheyu

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2020 省选模拟测试 Round #8 solution (20/02/07)相关的知识,希望对你有一定的参考价值。

【比赛链接】http://59.61.75.5:8018/contest/218

A. 并

【题意】

一棵 $n$ 个点的树有 $n-1$ 条边,分别为 $(u_1,v_1),(u_2,v_2),cdots,(u_{n-1},v_{n-1})$. 开始时,对每个点 $u$,有集合 $S_u={u}$。

有 $m$ 个操作,第 $i$ 次操作给定 $p_i$,将 $S_{u_{p_i}}$ 与 $S_{v_{p_i}}$ 赋为它们的并。

所有操作结束后,对所有的 $iin[1,n]$,求包含 $i$ 的集合的数目。

【数据范围】$n,mle 5 imes 10^5$。

【题解】

考虑每个点什么时候会被统计。显然每次包含其连通块的操作都会影响。将操作反序处理,统计一下即可。

效率 $O(m+n)$。期望得分:100。

【代码】

技术图片
 1 #include<bits/stdc++.h>
 2 int n,m,u[500010],v[500010],s[500010],val[500010],q[500010];
 3 signed main()
 4 {
 5     scanf("%d%d",&n,&m);
 6     for ( int i=1;i<n;i++ ) scanf("%d%d",&u[i],&v[i]);
 7     for ( int i=1;i<=n;i++ ) s[i]=1;
 8     for ( int i=1;i<=m;i++ ) scanf("%d",&q[i]);
 9     for ( int i=m,x;i;i-- ) x=q[i],s[u[x]]=s[v[x]]=s[u[x]]+s[v[x]]-val[x],val[x]=s[u[x]];
10     for ( int i=1;i<=n;i++ ) printf("%d%c",s[i]," 
"[i==n]);
11     return 0;
12 }
DTOJ4710

C. 管理

【题意】

一排 $n$ 个物品,第 $i$ 个物品权值为 $a_i$,请将其分成恰好 $k$ 非空段,且让同段中 $a_i$? 相同的二元组 $(i,j)$ 尽量少。亦即,假设在第 $i$ 段里权值为 $j$ 物品有 $c(i,j)$ 个,则请最小化 $sumlimits_{i=1}^ksumlimits_{j}inom{c(i,j)}{2}$。

【数据范围】$2le nle 10^5,,1le kle min{n,20},,1le a_ile n$。

【题解】

考虑 $dp$。设 $f[i][j]$ 表示前 $i$ 个数分为 $k$ 段的最小值。则有:$f[i][j]=minlimits_{0leq k <i}(f[k][j-1]+w(k+1,i))$。

对于 $k$,由于 $k$ 较小,显然可以分层处理,即对每一层 $j$ 分别转移。

打表发现具有决策单调性。又无法用指针或单调队列维护具体情况,考虑用分治法处理决策单调性。

考虑如何计算 $w(l,r)$。显然可以由 $w(l,r)$ 推至 $w(l-1,r)$ 等类似位置。因此用类似莫队的方法进行维护即可。

效率 $O(nklog n)$。期望得分:100。

技术图片
 1 #include<bits/stdc++.h>
 2 const long long inf=1LL<<60;
 3 int n,k,cnt[100010],a[100010],pl,pr;
 4 long long f[100010][22],res;
 5 inline void Ins ( int x,int v ) { res-=1LL*cnt[x]*(cnt[x]-1)/2;cnt[x]+=v;res+=1LL*cnt[x]*(cnt[x]-1)/2; }
 6 inline void solve ( int l,int r,int L,int R,int k )
 7 {
 8     int mid=(l+r)>>1;
 9     while ( pl>L+1 ) Ins(a[--pl],1);
10     while ( pr<mid ) Ins(a[++pr],1);
11     while ( pl<L+1 ) Ins(a[pl++],-1);
12     while ( pr>mid ) Ins(a[pr--],-1);
13     int p=L;long long ans=f[L][k-1]+res;
14     while ( pl<=mid and pl<=R+1 )
15     {
16         if ( f[pl-1][k-1]+res<=ans ) ans=f[pl-1][k-1]+res,p=pl-1;
17         Ins(a[pl++],-1);
18     }
19     f[mid][k]=ans;
20     if ( l<=mid-1 ) solve(l,mid-1,L,p,k);
21     if ( mid+1<=r ) solve(mid+1,r,p,R,k);
22 }
23 signed main()
24 {
25     scanf("%d%d",&n,&k);
26     for ( int i=1;i<=n;i++ ) scanf("%d",&a[i]);
27     for ( int i=0;i<=n;i++ ) for ( int j=0;j<=k;j++ ) f[i][j]=inf;
28     f[0][0]=0;
29     for ( int j=1;j<=k;j++ )
30     {
31         res=0;pl=1;pr=n;
32         for ( int i=1;i<=n;i++ ) cnt[i]=0;
33         for ( int i=1;i<=n;i++ ) Ins(a[i],1);
34         solve(1,n,0,n-1,j);
35     }
36     return !printf("%lld
",f[n][k]);
37 }
DTOJ4718

以上是关于2020 省选模拟测试 Round #8 solution (20/02/07)的主要内容,如果未能解决你的问题,请参考以下文章

2020.05.16省选B组模拟 总结

2020.05.16省选B组模拟 总结

2020.07.30省选B组模拟 总结

2020.01.10省选组模拟 总结

6700. 2020.06.07省选模拟得分

6700. 2020.06.07省选模拟得分