当前位置: 首页 > news >正文

2.6 寒假训练营补题

C Tokitsukaze and Balance String (hard)

题目描述

本题为《Tokitsukaze and Balance String (easy)》的困难版本,两题的唯一区别在于 n n n 的范围。

一个字符串是平衡的,当且仅当字符串中 "01" 连续子串的个数与 "10" 连续子串的个数相同。

定义字符串 s s s v a l ( s ) val(s) val(s) 为这样的位置数量:

  • 若当前位置上的字符为 '0',将其反置后成为 '1',此时字符串 s s s 是平衡的;
  • 若当前位置上的字符为 '1',将其反置后成为 '0',此时字符串 s s s 是平衡的。

现在 Tokitsukaze 有一个长度为 n n n,仅由字符 '0''1''?' 构成的字符串 s s s

其中,'?' 可以替换成 '0' 或者 '1'。假设 '?' 的个数为 p p p,显然将每个 '?' 都替换后,总共可以得到 2 p 2^p 2p 个不同的 s s s,Tokitsukaze 想知道所有 2 p 2^p 2p 个不同的 s s s 对应的 v a l ( s ) val(s) val(s) 之和是多少。由于答案可能很大,请将答案对 ( 1 0 9 + 7 ) (10^9 + 7) (109+7) 取模后输出。

子串为从原字符串中,连续的选择一段字符(可以全选、可以不选)得到的新字符串。

输入描述

每个测试文件均包含多组测试数据。第一行输入一个整数 T ( 1 ≤ T ≤ 2 × 1 0 5 ) T(1\leq T\leq 2\times 10^5) T(1T2×105) 代表数据组数,每组测试数据描述如下:

  • 第一行输入一个整数 n ( 1 ≤ n ≤ 2 × 1 0 5 ) n(1\leq n\leq 2\times 10^5) n(1n2×105) 代表字符串长度。
  • 第二行输入一个长度为 n n n、仅由 '0''1''?' 构成的字符串 s s s

除此之外,保证单个测试文件的 n n n 之和不超过 2 × 1 0 5 2\times 10^5 2×105

输出描述

对于每一组测试数据,新起一行。输出一个整数,代表全部 2 p 2^p 2p 个不同的 s s s 对应的 v a l ( s ) val(s) val(s) 之和。由于答案可能很大,请将答案对 ( 1 0 9 + 7 ) (10^9 + 7) (109+7) 取模后输出。

示例

输入

5
1
0
4
??01
5
?????
10
010??1101?
50
??1??0?0???????0?1??00?1???1??0?11??1011001???00??

输出

1
8
80
40
421772709

说明

  • 对于第一组测试数据,反置字符串的第一个字符,得到字符串 "1",此时,"01" 子串与 "10" 子串个数均为 0 0 0,平衡。由于在这个样例中,只有一种不同的 s s s,所以答案即为 v a l ( " 1 " ) = 1 val("1") = 1 val("1")=1
  • 对于第二组测试数据,通过替换 '?' 得到 4 4 4 种不同的 s s s,分别为:"0001""0101""1001""1101"。限制于篇幅,我们在此仅详细展开讨论 "0001" 的情况。
    • 翻转第一个字符,得到 "1001",此时,"01" 子串与 "10" 子串个数均为 1 1 1,平衡。
    • 翻转第二个字符,得到 "0101",此时,"01" 子串个数为 2 2 2"10" 子串个数为 1 1 1,不平衡。
    • 翻转第三个字符,得到 "0011",此时,"01" 子串个数为 1 1 1"10" 子串个数为 0 0 0,不平衡。
    • 翻转第四个字符,得到 "0000",此时,"01" 子串与 "10" 子串个数均为 0 0 0,平衡。
      综上,得到 v a l ( " 0001 " ) = 2 val("0001") = 2 val("0001")=2。同理可得其他三个字符串。最终答案为 2 + 2 + 2 + 2 = 8 2 + 2 + 2 + 2 = 8 2+2+2+2=8

解题思路

核心性质

对于长度为 n n n 的 01 字符串 s s s,当 s 1 s_1 s1 s n s_n sn 相等时,“01” 与 “10” 子串数量相等。所以在 2 ≤ i ≤ n − 1 2\leq i\leq n - 1 2in1 范围内的 ? 可以随意填充,不会影响 “01” 与 “10” 子串的数量。

定义变量

2 ≤ i ≤ n − 1 2\leq i\leq n - 1 2in1 中的 ? 个数为 c n t cnt cnt

不考虑 s 1 s_1 s1 s n s_n sn? 的情况

情况一: s 1 = s n s_1 = s_n s1=sn

s 1 s_1 s1 等于 s n s_n sn 时, 2 ≤ i ≤ n − 1 2\leq i\leq n - 1 2in1 中的 s i s_i si 可以随意翻转。此时 v a l ( s ) = n − 2 val(s)=n - 2 val(s)=n2,那么这部分对结果的贡献为 2 c n t ⋅ ( n − 2 ) 2^{cnt}\cdot(n - 2) 2cnt(n2)

情况二: s 1 ≠ s n s_1 \neq s_n s1=sn

s 1 s_1 s1 不等于 s n s_n sn 时,必须翻转 s 1 s_1 s1 或者 s n s_n sn 才能使字符串满足条件,即 v a l ( s ) = 2 val(s)=2 val(s)=2,这部分对结果的贡献为 2 c n t ⋅ 2 2^{cnt}\cdot2 2cnt2

考虑 s 1 s_1 s1 s n s_n sn? 的情况

s 1 s_1 s1 s n s_n sn? 时,需要再进行分类讨论,具体细节可参考后续代码实现。

优化点

由于 c n t cnt cnt 最多等于 n − 2 n - 2 n2,我们可以对 2 2 2 的幂进行预处理,这样就不需要使用快速幂算法,能将时间复杂度控制在 O ( n ) O(n) O(n)

代码

#include <bits/stdc++.h>
#define int long long
using namespace std;
const int mod= 1e9+7;
int qpow(int a,int b)
{int res=1;while(b){if(b&1)res=res*a%mod;a=a*a%mod;b/=2;}return res;
}
void solve()
{int n;cin>>n;string s;cin>>s;s=" "+s;if(n==1){if(s[1]!='?')cout<<1<<'\n';else cout<<2<<'\n';}else{int cnt=0;for(int i=2;i<=n-1;i++)if(s[i]=='?')cnt++;int ans=qpow(2,cnt);if(s[1]==s[n]){if(s[1]!='?')ans=ans*(n-2)%mod;else ans=ans*2*n%mod;}else{if(s[1]=='?' && s[n]!='?')ans=ans*n%mod;else if(s[1]!='?' && s[n]=='?')ans=ans*n%mod;else ans=ans*2%mod;}cout<<ans<<'\n';}
}signed main()
{  int t;cin>>t;while(t--)solve();return 0;
}

A Tokitsukaze and Absolute Expectation

题目描述

Tokitsukaze 有一个由 n n n 个整数组成的序列 { a 1 , a 2 , … , a n } \{a_1, a_2, \ldots, a_n\} {a1,a2,,an},其中第 i i i 个元素 a i a_i ai 的值在区间 [ l i , r i ] [l_i, r_i] [li,ri] 中独立地、等概率随机生成。

定义一个序列的价值为 v a l ( a ) = ∑ i = 2 n ∣ a i − 1 − a i ∣ val(a)=\sum_{i = 2}^{n}|a_{i - 1}-a_i| val(a)=i=2nai1ai,Tokitsukaze 想知道 v a l ( a ) val(a) val(a) 的期望。

输入描述

每个测试文件均包含多组测试数据。第一行输入一个整数 T ( 1 ≤ T ≤ 1 0 5 ) T(1\leq T\leq 10^5) T(1T105) 代表数据组数,每组测试数据描述如下:

  • 第一行输入一个整数 n ( 2 ≤ n ≤ 2 × 1 0 5 ) n(2\leq n\leq 2\times 10^5) n(2n2×105) 代表序列中元素的数量。
  • 此后 n n n 行,第 i i i 行输入两个整数 l i , r i ( 1 ≤ l i ≤ r i ≤ 1 0 9 ) l_i, r_i(1\leq l_i\leq r_i\leq 10^9) li,ri(1liri109) 代表第 i i i 个元素的取值范围。

除此之外,保证单个测试文件的 n n n 之和不超过 2 × 1 0 5 2\times 10^5 2×105

输出描述

可以证明答案可以表示为一个不可约分数 p q \frac{p}{q} qp,为了避免精度问题,请直接输出整数 ( p ⋅ q − 1 m o d M ) (p\cdot q^{-1}\bmod M) (pq1modM) 作为答案,其中 M = 1 0 9 + 7 M = 10^9 + 7 M=109+7 q − 1 q^{-1} q1 是满足 q × q − 1 ≡ 1 ( m o d M ) q\times q^{-1}\equiv 1(\bmod M) q×q11(modM) 的整数。

更具体地,你需要找到一个整数 x ∈ [ 0 , 1 0 9 + 7 ) x\in[0, 10^9 + 7) x[0,109+7) 满足 x × q x\times q x×q 1 0 9 + 7 10^9 + 7 109+7 取模等于 p p p,您可以查看样例解释得到更具体的说明。

示例

输入

2
3
1 2
1 2
1 3
4
4 8
2 3
4 10
4 7

输出

333333337
214285726

说明

对于第一组测试数据,总共有 12 12 12 种序列,每种序列出现的概率均相等,如下:

  • v a l ( { 1 , 1 , 1 } ) = ∣ 1 − 1 ∣ + ∣ 1 − 1 ∣ = 0 val(\{1, 1, 1\}) = |1 - 1|+|1 - 1| = 0 val({1,1,1})=∣11∣+∣11∣=0
  • v a l ( { 1 , 1 , 2 } ) = ∣ 1 − 1 ∣ + ∣ 1 − 2 ∣ = 1 val(\{1, 1, 2\}) = |1 - 1|+|1 - 2| = 1 val({1,1,2})=∣11∣+∣12∣=1
  • v a l ( { 1 , 1 , 3 } ) = ∣ 1 − 1 ∣ + ∣ 1 − 3 ∣ = 2 val(\{1, 1, 3\}) = |1 - 1|+|1 - 3| = 2 val({1,1,3})=∣11∣+∣13∣=2
  • v a l ( { 1 , 2 , 1 } ) = ∣ 1 − 2 ∣ + ∣ 2 − 1 ∣ = 2 val(\{1, 2, 1\}) = |1 - 2|+|2 - 1| = 2 val({1,2,1})=∣12∣+∣21∣=2
  • v a l ( { 1 , 2 , 2 } ) = ∣ 1 − 2 ∣ + ∣ 2 − 2 ∣ = 1 val(\{1, 2, 2\}) = |1 - 2|+|2 - 2| = 1 val({1,2,2})=∣12∣+∣22∣=1
  • v a l ( { 1 , 2 , 3 } ) = ∣ 1 − 2 ∣ + ∣ 2 − 3 ∣ = 2 val(\{1, 2, 3\}) = |1 - 2|+|2 - 3| = 2 val({1,2,3})=∣12∣+∣23∣=2
  • v a l ( { 2 , 1 , 1 } ) = ∣ 2 − 1 ∣ + ∣ 1 − 1 ∣ = 1 val(\{2, 1, 1\}) = |2 - 1|+|1 - 1| = 1 val({2,1,1})=∣21∣+∣11∣=1
  • v a l ( { 2 , 1 , 2 } ) = ∣ 2 − 1 ∣ + ∣ 1 − 2 ∣ = 2 val(\{2, 1, 2\}) = |2 - 1|+|1 - 2| = 2 val({2,1,2})=∣21∣+∣12∣=2
  • v a l ( { 2 , 1 , 3 } ) = ∣ 2 − 1 ∣ + ∣ 1 − 3 ∣ = 3 val(\{2, 1, 3\}) = |2 - 1|+|1 - 3| = 3 val({2,1,3})=∣21∣+∣13∣=3
  • v a l ( { 2 , 2 , 1 } ) = ∣ 2 − 2 ∣ + ∣ 2 − 1 ∣ = 1 val(\{2, 2, 1\}) = |2 - 2|+|2 - 1| = 1 val({2,2,1})=∣22∣+∣21∣=1
  • v a l ( { 2 , 2 , 2 } ) = ∣ 2 − 2 ∣ + ∣ 2 − 2 ∣ = 0 val(\{2, 2, 2\}) = |2 - 2|+|2 - 2| = 0 val({2,2,2})=∣22∣+∣22∣=0
  • v a l ( { 2 , 2 , 3 } ) = ∣ 2 − 2 ∣ + ∣ 2 − 3 ∣ = 1 val(\{2, 2, 3\}) = |2 - 2|+|2 - 3| = 1 val({2,2,3})=∣22∣+∣23∣=1

综上所述,期望值为 0 + 1 + 2 + 2 + 1 + 2 + 1 + 2 + 3 + 1 + 0 + 1 12 = 4 3 \frac{0 + 1+2 + 2+1 + 2+1 + 2+3 + 1+0 + 1}{12}=\frac{4}{3} 120+1+2+2+1+2+1+2+3+1+0+1=34。我们能够找到, 333333337 × 3 = 1000000011 333333337\times 3 = 1000000011 333333337×3=1000000011,对 1 0 9 + 7 10^9 + 7 109+7 取模后恰好等于分子 4 4 4,所以 333333337 333333337 333333337 是需要输出的答案。

解题思路

链接:https://ac.nowcoder.com/discuss/1454104
来源:牛客网

核心转化

根据期望的线性性质,可以转化成求 ∣ a i − a i − 1 ∣ |a_i - a_{i - 1}| aiai1 的期望之和。那么问题就转化成了 ∣ a i − a i − 1 ∣ |a_i - a_{i - 1}| aiai1 的期望。

分母计算

由于 a i − 1 a_{i - 1} ai1 a i a_i ai 在区间 [ l i − 1 , r i − 1 ] [l_{i - 1}, r_{i - 1}] [li1,ri1] [ l i , r i ] [l_i, r_i] [li,ri] 等概率随机,所以分母为 ( r i − 1 − l i − 1 + 1 ) ⋅ ( r i − l i + 1 ) (r_{i - 1}-l_{i - 1}+1)\cdot(r_i - l_i + 1) (ri1li1+1)(rili+1)

分子计算

分子是 a i − 1 a_{i - 1} ai1 a i a_i ai 绝对值之差的所有情况之和。假设目前计算的是 [ l 1 , r 1 ] [l_1, r_1] [l1,r1] [ l 2 , r 2 ] [l_2, r_2] [l2,r2]。设 [ x , y ] [x, y] [x,y] 为这两个区间的交,即 x = max ⁡ ( l 1 , l 2 ) x = \max(l_1, l_2) x=max(l1,l2) y = min ⁡ ( r 1 , r 2 ) y=\min(r_1, r_2) y=min(r1,r2)。然后通过下面 3 个部分进行计算:

  1. [ l 1 , x − 1 ] [l_1, x - 1] [l1,x1] [ l 2 , r 2 ] [l_2, r_2] [l2,r2]
  2. [ x , y ] [x, y] [x,y] [ y + 1 , r 2 ] [y + 1, r_2] [y+1,r2]
  3. [ x , y ] [x, y] [x,y] [ x , y ] [x, y] [x,y]

情况 1 和情况 2 很好算,因为它们区间都没有交。实现可以参考代码中的 cal2 函数。

情况 3 因为它是对称的,可以推出一个式子。式子可以参考代码中的 cal3 函数。

复杂度分析

求完分子就做完了。由于每次需要求一下分母的逆元,所以时间复杂度为 O ( n log ⁡ m ) O(n\log m) O(nlogm) m = 1 0 9 + 7 m = 10^9 + 7 m=109+7

代码

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MAX=5e5+10;
const int mod=1e9+7;
ll qpow(ll a,ll b)
{ll res=1;while(b>0){if(b&1) res=res*a%mod;a=a*a%mod;b>>=1;}return res;
}
ll inv(ll x){return qpow(x,mod-2);}
const ll inv3=inv(3);
ll cal3(int l,int r)
{int n=r-l+1;return 1LL*(n-1)*n%mod*(n+1)%mod*inv3%mod;
}
ll cal2(int l1,int r1,int l2,int r2)
{if(l1>r1||l2>r2) return 0;ll res=0;res+=1LL*(l2+r2)*(r2-l2+1)/2%mod*(r1-l1+1);res-=1LL*(l1+r1)*(r1-l1+1)/2%mod*(r2-l2+1);res%=mod;if(res<0) return res+mod;return res;
}
ll cal(int l1,int r1,int l2,int r2)
{if(l1>l2){swap(l1,l2);swap(r1,r2);}int x,y;x=max(l1,l2);y=min(r1,r2);if(x>y) return cal2(l1,r1,l2,r2);ll res=0;res+=cal2(l1,x-1,l2,r2);res+=cal2(x,y,y+1,max(r1,r2));res+=cal3(x,y);return res%mod;
}
int l[MAX],r[MAX];
signed main()
{int t,n,i;ll ans,fz,fm;scanf("%d",&t);while(t--){scanf("%d",&n);for(i=1;i<=n;i++) scanf("%d%d",&l[i],&r[i]);ans=0;for(i=2;i<=n;i++){fz=cal(l[i-1],r[i-1],l[i],r[i]);fm=1LL*(r[i-1]-l[i-1]+1)*(r[i]-l[i]+1)%mod;ans=(ans+fz*inv(fm))%mod;}printf("%lld\n",ans);}return 0;
}

F Tokitsukaze and Kth Problem (easy)

题目描述

本题与《Tokitsukaze and Kth Problem (hard)》共享题目背景,可以视作困难版本的子问题。若能通过 hard,在做简单修改后,必能通过 easy。

Tokitsukaze 有一个由 n n n 个整数组成的序列 { a 1 , a 2 , … , a n } \{a_1, a_2, \ldots, a_n\} {a1,a2,,an}。他定义一个二元组 ( i , j ) (i, j) (i,j) 满足 1 ≤ i < j ≤ n 1\leq i < j\leq n 1i<jn,并定义这个二元组对应的值 f ( i , j ) = ( a i + a j ) m o d p f(i,j)=(a_i + a_j)\bmod p f(i,j)=(ai+aj)modp

他想知道,对于全部不同的二元组 ( i , j ) (i, j) (i,j),全部值 f ( i , j ) f(i,j) f(i,j) 的前 k k k 大值分别为多少。如果不存在,则输出 − 1 -1 1 替代。

输入描述

每个测试文件均包含多组测试数据。第一行输入一个整数 T ( 1 ≤ T ≤ 1 0 5 ) T(1\leq T\leq 10^5) T(1T105) 代表数据组数,每组测试数据描述如下:

  • 第一行输入三个整数 n , p , k ( 2 ≤ n ≤ 2 × 1 0 5 ; 1 ≤ p ≤ 1 0 9 ; 1 ≤ k ≤ 2 × 1 0 5 ) n, p, k(2\leq n\leq 2\times 10^5; 1\leq p\leq 10^9; 1\leq k\leq 2\times 10^5) n,p,k(2n2×105;1p109;1k2×105) 代表序列中的元素数量、模数、询问大小。
  • 第二行输入 n n n 个整数 a 1 , a 2 , … , a n ( 0 ≤ a i ≤ 1 0 9 ) a_1, a_2, \ldots, a_n(0\leq a_i\leq 10^9) a1,a2,,an(0ai109) 代表序列中的元素。

除此之外,保证单个测试文件的 n n n 之和不超过 2 × 1 0 5 2\times 10^5 2×105 k k k 之和不超过 2 × 1 0 5 2\times 10^5 2×105

输出描述

对于每一组测试数据,新起一行。连续输出 k k k 个整数,第 x x x 个整数表示 f ( i , j ) f(i,j) f(i,j) 的第 x x x 大值,如果不存在第 x x x 大值,输出 − 1 -1 1 替代。

示例

输入

3
3 10 8
2 4 8
4 6 4
1 2 3 3
5 10 10
1 2 3 4 5

输出

6 2 0 -1 -1 -1 -1 -1
5 5 4 4
9 8 7 7 6 6 5 5 4 3

说明

对于第二组测试数据,一共有六个不同的二元组,对应的值分别为:

  • f ( 1 , 2 ) = ( 1 + 2 ) m o d 6 = 3 f(1,2)=(1 + 2)\bmod 6 = 3 f(1,2)=(1+2)mod6=3
  • f ( 1 , 3 ) = ( 1 + 3 ) m o d 6 = 4 f(1,3)=(1 + 3)\bmod 6 = 4 f(1,3)=(1+3)mod6=4
  • f ( 1 , 4 ) = ( 1 + 3 ) m o d 6 = 4 f(1,4)=(1 + 3)\bmod 6 = 4 f(1,4)=(1+3)mod6=4
  • f ( 2 , 3 ) = ( 2 + 3 ) m o d 6 = 5 f(2,3)=(2 + 3)\bmod 6 = 5 f(2,3)=(2+3)mod6=5
  • f ( 2 , 4 ) = ( 2 + 3 ) m o d 6 = 5 f(2,4)=(2 + 3)\bmod 6 = 5 f(2,4)=(2+3)mod6=5
  • f ( 3 , 4 ) = ( 3 + 3 ) m o d 6 = 0 f(3,4)=(3 + 3)\bmod 6 = 0 f(3,4)=(3+3)mod6=0

排序后得到 { 0 , 3 , 4 , 4 , 5 , 5 } \{0, 3, 4, 4, 5, 5\} {0,3,4,4,5,5}

解题思路

Solution 1:二分答案

这类求第 k k k 大,或者前 k k k 大类的题,一般可以先考虑二分答案。

  • 由于 easy 版本与序列顺序无关,所以可以先对序列进行排序(sort),然后二分答案后用双指针数一下有多少对大于等于答案。
  • 求出第 k k k 大后,大于答案的对可以暴力求出来,剩下的再用答案填。

时间复杂度 O ( n log ⁡ V + k ) O(n\log V + k) O(nlogV+k),其中 V V V 为值域。

代码链接:https://ac.nowcoder.com/acm/contest/view-submission?submissionId=75401127

Solution 2:堆

我们可以构造一种方案,使得堆内必定存在当前的最大值。这样只要从堆中弹出 k k k 次就是前 k k k 大。

  • 对于这道题,可以枚举 a i a_i ai,对于每个 a i a_i ai,找到与它匹配能使 f ( i , j ) f(i,j) f(i,j) 最大的 a j a_j aj 放入堆中。
  • 每次从堆中弹出一个东西,我们就把下一个与 a i a_i ai 匹配的 a j a_j aj 放入堆中(如果有的话)。

时间复杂度 O ( ( n + k ) log ⁡ n ) O((n + k)\log n) O((n+k)logn)

代码链接:https://ac.nowcoder.com/acm/contest/view-submission?submissionId=75401133

代码

#include<bits/stdc++.h>
using namespace std;
const int N = 1000010, mod = 1e9 + 7;
#define int long long 
int a[N], b[N];
int n, m, k;
void solve() {int p;cin >> n >> p >> k;for (int i = 1; i <= n; i++) {cin >> a[i];a[i] %= p;}sort(a + 1, a + 1 + n);auto work = [&](int x) -> long long {int ans = 0;for (int i = 1, j = n; i <= n; i++) {while (j >= 1 && a[i] + a[j] >= x) j--;if (j > i)  ans += n - j;else ans += n - i;}return ans;};auto check = [&](int x) -> long long {return work(x) + work(p + x) - work(p);};int l = 0, r = p - 1;while (l <= r) {int mid = l + r >> 1;if (check(mid) >= k)  l = mid + 1;else r = mid - 1;}vector<int> ans;for (int i = 1, j = n, c = n; i <= n; i++) {while (j >= 1 && a[i] + a[j] >= l) j--;while (c >= 1 && a[i] + a[c] >= l + p) c--;for (int ii = max(i, j) + 1; ii <= n; ii++) {if (a[i] + a[ii] >= p)  break;ans.push_back(a[i] + a[ii]);}for (int ii = max(i, c) + 1; ii <= n; ii++)ans.push_back((a[i] + a[ii]) % p);}while (ans.size() < k)  ans.push_back(r);sort(ans.begin(), ans.end(), greater<int>());for (auto t : ans)  cout << t << ' ';cout << '\n';
}
signed main() {ios::sync_with_stdio(0);cin.tie(0); cout.tie(0);int t = 1;cin >> t;while (t--) {solve();}return 0;
}

J Tokitsukaze and Recall

题目描述

在初代《星际争霸》中,神族的仲裁者有“recall”技能,可将一定范围的我方部队从地图任意地点传送到仲裁者所在位置,且仲裁者可部署在任意敌方区域上空,能使用任意次该技能。

Tokitsukaze 玩“岛屿”地图,地图区域不一定连通,敌方占领 n n n 块区域,有 m m m 条双向道路连接不同区域。我方部队可在已占领区域随意移动,但无法穿过敌方占领区域,不过可通过在目标区域部署仲裁者使用“recall”技能将部队传送过去。

Tokitsukaze 有一个无敌地面部队,部队初始在区域 0 0 0(与敌方区域不相连),她只能建造 k k k 个仲裁者,想合理部署以尽可能多地占领敌方区域。要求输出最多能占领的敌方区域数量,以及按占领顺序输出区域编号,若有多种方案,输出字典序最小的那种。

字典序规则:数组 c c c 在字典序上小于数组 d d d 当且仅当以下任一情况成立:

  • ∣ c ∣ < ∣ d ∣ |c| < |d| c<d 并且对于所有 1 ≤ i ≤ ∣ c ∣ 1\leq i\leq |c| 1ic 满足 c i = d i c_i = d_i ci=di,其中 ∣ c ∣ |c| c 表示数组 c c c 的长度;
  • c c c d d d 不同的第一个位置上,数组 c c c 的元素小于数组 d d d 中对应的元素。

输入描述

每个测试文件均包含多组测试数据。第一行输入一个整数 T ( 1 ≤ T ≤ 2 × 1 0 5 ) T(1\leq T\leq 2\times 10^5) T(1T2×105) 代表数据组数,每组测试数据描述如下:

  • 第一行输入三个整数 n , m , k ( 1 ≤ k ≤ n ≤ 2 × 1 0 5 ; 0 ≤ m ≤ min ⁡ { n × ( n − 1 ) 2 , 5 × 1 0 5 } ) n, m, k(1\leq k\leq n\leq 2\times 10^5; 0\leq m\leq \min\{\frac{n\times(n - 1)}{2}, 5\times 10^5\}) n,m,k(1kn2×105;0mmin{2n×(n1),5×105}) 代表地图区域数量、双向道路数量、仲裁者数量。
  • 此后 m m m 行,第 i i i 行输入两个整数 u i , v i ( 1 ≤ u i , v i ≤ n ; u i ≠ v i ) u_i, v_i(1\leq u_i, v_i\leq n; u_i\neq v_i) ui,vi(1ui,vin;ui=vi) 代表第 i i i 条双向道路连接区域 u i u_i ui v i v_i vi。保证不存在重复道路,即每两块区域之间最多只有一条道路直接连接。

除此之外,保证单个测试文件的 n n n 之和不超过 2 × 1 0 5 2\times 10^5 2×105 m m m 之和不超过 5 × 1 0 5 5\times 10^5 5×105

输出描述

对于每一组测试数据,输出两行:

  • 第一行输出一个整数 s ( 1 ≤ s ≤ n ) s(1\leq s\leq n) s(1sn) 代表 Tokitsukaze 最多占领的敌方区域数量。
  • 第二行输出 s s s 个互不相同的整数 c 1 , c 2 , … , c s ( 1 ≤ c i ≤ n ) c_1, c_2, \ldots, c_s(1\leq c_i\leq n) c1,c2,,cs(1cin),第 i i i 个整数 c i c_i ci 表示 Tokitsukaze 第 i i i 次占领的是区域 c i c_i ci。如果有多种方案,输出字典序最小的那种。

示例

示例 1

输入
5
4 3 1
2 1
1 3
3 4
4 3 1
1 3
3 4
4 2
4 3 2
1 3
3 4
4 2
5 3 1
1 2
3 4
4 5
6 4 1
1 2
2 6
3 4
4 5
输出
4
1 2 3 4
4
1 3 4 2
4
1 2 3 4
3
3 4 5
3
1 2 6
说明
  • 对于第一组测试数据:将仅有 1 1 1 个仲裁者部署在区域 1 1 1,Tokitsukaze 将部队传送到区域 1 1 1 并占领;接着让部队到达区域 2 2 2 并占领;接着让部队从区域 2 2 2 回到区域 1 1 1,然后前往区域 3 3 3 并占领;最后让部队从区域 3 3 3 前往区域 4 4 4 并占领。所以占领的顺序是 { 1 , 2 , 3 , 4 } \{1, 2, 3, 4\} {1,2,3,4}
  • 对于第二组测试数据:将仅有 1 1 1 个仲裁者部署在区域 1 1 1,Tokitsukaze 将部队传送到区域 1 1 1 并占领;接着让部队到达区域 3 3 3 并占领;接着让部队从区域 3 3 3 前往区域 4 4 4 并占领;最后让部队从区域 4 4 4 前往区域 2 2 2 并占领。所以占领的顺序是 { 1 , 3 , 4 , 2 } \{1, 3, 4, 2\} {1,3,4,2}
  • 对于第三组测试数据:将 2 2 2 个仲裁者分别部署在区域 1 1 1 和区域 2 2 2
  • 对于第四组测试数据:将 1 1 1 个仲裁者部署在区域 1 1 1 或者区域 2 2 2 只能占领 2 2 2 个敌方区域;而部署在区域 3 3 3 4 4 4 5 5 5 中任意一个区域,均可以占领 3 3 3 个敌方区域,并且部署在区域 3 3 3 可以使占领顺序的区域编号字典序最小,占领的顺序为 { 3 , 4 , 5 } \{3, 4, 5\} {3,4,5}
  • 对于第五组测试数据:将 1 1 1 个仲裁者部署在区域 1 1 1 2 2 2 6 6 6 中任意一个区域可以占领 3 3 3 个敌方区域;部署在区域 3 3 3 4 4 4 5 5 5 中任意一个区域也可以占领 3 3 3 个敌方区域。字典序最小的方案是部署在区域 1 1 1,占领顺序为 { 1 , 2 , 6 } \{1, 2, 6\} {1,2,6}

示例 2

输入
4
4 0 1
4 0 2
4 0 3
4 0 4
输出
1
1
2
1 2
3
1 2 3
4
1 2 3 4

解题思路

整体思路

题目要求访问到的点数最多,并且访问顺序的字典序最小。可以分两步解决:先求出能访问到的最多点数,再考虑访问顺序的字典序最小。

解决点数最多的问题

求出每个连通块有多少个点,并按点的数量从大到小排序。优先选择点数前 k k k 多的连通块;如果 k k k 大于等于连通块个数,则可以全选。

考虑字典序最小

  • 选择连通块时:如果两个连通块的点数相同但只能选一个,设连通块内编号最小的节点的编号为 m n mn mn,在排序时,优先选择 m n mn mn 小的那个连通块。
  • 统计连通块信息:统计连通块内节点个数与最小编号可以建图后使用深度优先搜索(dfs)或者并查集实现。
  • 维护可访问节点:为了使字典序最小,用一个优先队列来维护所有可访问的节点,每次弹出最小编号。
  • 部署仲裁者:因为要求访问顺序字典序最小,所以仲裁者肯定会被部署在一个连通块的编号最小的节点上,即部署在连通块的 m n mn mn 节点。最初,把所有选择的连通块的 m n mn mn 节点都放入优先队列。
  • 处理剩余仲裁者:如果 k k k 大于连通块个数,即 k k k 还有剩余,可以把剩余的 k k k 服务于最小字典序。具体的,如果当前 k > 0 k > 0 k>0,并且存在编号比队列弹出来的编号更小的节点,那么直接在那个节点上部署是更优的。

复杂度分析

由于使用了优先队列,每个节点最多会入队出队一次,所以时间复杂度为 O ( n log ⁡ n ) O(n\log n) O(nlogn)

代码链接

https://ac.nowcoder.com/acm/contest/view-submission?submissionId=75401084

代码

#include<bits/stdc++.h>
#define int long long
using namespace std;
int n,m,f[2000005];
int ver[2000005],Next[2000005],head[2000005],tot;
int fa[2000005],sz[2000005],minn[2000005];
int ans[2000005],num;
struct node
{int mn,sz;
}t[2000005];
int cmp(node a,node b)
{if(a.sz==b.sz)return a.mn<b.mn;return a.sz>b.sz;
}
void add(int x,int y)
{ver[++tot]=y,Next[tot]=head[x],head[x]=tot;
}
int find(int x)
{if(x==fa[x])return fa[x];return fa[x]=find(fa[x]);
}
void merge(int x,int y)
{int t1=find(x),t2=find(y);if(t1!=t2){fa[t2]=t1;sz[t1]+=sz[t2];minn[t1]=min(minn[t1],minn[t2]);}
}
signed main()
{int tt;cin>>tt;while(tt--){int sum=0;tot=0,num=0;int k;cin>>n>>m>>k;for(int i=1;i<=n;i++){fa[i]=i;sz[i]=1;minn[i]=i;}for(int i=1;i<=m;i++){int x,y;cin>>x>>y;add(x,y);add(y,x);merge(x,y);}int cnt=0;map<int,int>mp;for(int i=1;i<=n;i++){if(!mp[find(i)]){t[++cnt].mn=minn[find(i)];t[cnt].sz=sz[find(i)];mp[find(i)]=1;}}sort(t+1,t+cnt+1,cmp);priority_queue<int>q;map<int,int>v;for(int i=1;i<=min(k,cnt);i++){sum+=t[i].sz;q.push(-t[i].mn);v[t[i].mn]=1;}if(k>=cnt)k-=cnt;elsek=0;int mex=1;while(q.size()){int u=-q.top();q.pop();ans[++num]=u;for(int i=head[u];i;i=Next[i]){int y=ver[i];if(!v[y]){q.push(-y);v[y]=1;}}if(k){int p=-q.top();if(p!=u+1){v[u+1]=1;q.push(-u-1);k--;}}}cout<<sum<<endl;for(int i=1;i<=sum;i++){cout<<ans[i]<<" ";}cout<<endl;for(int i=0;i<=n;i++){head[i]=0;ans[i]=0;t[i].sz=0;t[i].mn=0;}}return 0;
}

相关文章:

2.6 寒假训练营补题

C Tokitsukaze and Balance String (hard) 题目描述 本题为《Tokitsukaze and Balance String (easy)》的困难版本&#xff0c;两题的唯一区别在于 n n n 的范围。 一个字符串是平衡的&#xff0c;当且仅当字符串中 "01" 连续子串的个数与 "10" 连续子…...

kafka生产者之发送模式与ACK

文章目录 Kafka的发送模式Kafka的ack机制发送模式与ack的关联重试次数总结 在Kafka中&#xff0c;发送模式与ack机制紧密相关&#xff0c;它们共同影响着消息发送的可靠性和性能。 Kafka的发送模式 发后即忘&#xff08;Fire and Forget&#xff09;&#xff1a;生产者发送消息…...

笔记:蓝桥杯python搜索(3-2)——DFS剪支和记忆化搜索

目录 一、DFS剪支 二、例题 P2942 数字王国之军训军队 P3075 特殊的多边形 三、记忆化搜索 四、例题 例题 P3820 混境之地 P216 地宫取宝 一、DFS剪支 在搜索过程中&#xff0c;如果需要完全遍历所有情况可能需要很多时间在搜索到某种状态时&#xff0c;根据当前状态判断…...

ChatBox+硅基流动Deepseek_R1开源API 满血(671B)部署教程,全程干货无废话

DeepSeek开源深度推理模型火爆发布&#xff0c;网络流量过大经常导致服务器崩溃&#xff0c;所以一般有两种方法解决这个问题 如果你的硬件支持&#xff0c;或者保密文档&#xff0c;保密单位&#xff0c;那么可以部署在本地端。但是再好的电脑也不能让DS满血复活&#xff0c;…...

35~37.ppt

目录 35.张秘书-《会计行业中长期人才发展规划》 题目​ 解析 36.颐和园公园&#xff08;25张PPT) 题目​ 解析 37.颐和园公园&#xff08;22张PPT) 题目 解析 35.张秘书-《会计行业中长期人才发展规划》 题目 解析 插入自定义的幻灯片&#xff1a;新建幻灯片→重用…...

畅快使用DeepSeek-R1的方法

腾讯云API接入Cherry Studio简明指南-畅快使用DeepSeek-R1 注意&#xff1a;腾讯云API针对deepseek限时免费&#xff08;后续即使收费也较为便宜&#xff0c;可以作为长期使用的方法&#xff09;&#xff0c;并且比华为的API要快不少。 一、获取腾讯云API密钥 登录并进入腾讯…...

【人工智能】Python中的序列到序列(Seq2Seq)模型:实现机器翻译

《Python OpenCV从菜鸟到高手》带你进入图像处理与计算机视觉的大门! 解锁Python编程的无限可能:《奇妙的Python》带你漫游代码世界 序列到序列(Seq2Seq)模型是自然语言处理(NLP)中一项核心技术,广泛应用于机器翻译、语音识别、文本摘要等任务。本文深入探讨Seq2Seq模…...

【算法】动态规划专题⑥ —— 完全背包问题 python

目录 前置知识进入正题模板 前置知识 【算法】动态规划专题⑤ —— 0-1背包问题 滚动数组优化 完全背包问题是动态规划中的一种经典问题&#xff0c;它与0-1背包问题相似&#xff0c;但有一个关键的区别&#xff1a;在完全背包问题中&#xff0c;每种物品都有无限的数量可用。…...

记一次基于manifest v3开发谷歌插件

背景 头疼在国际化功能普遍的前端项目中&#xff0c;如果你在处理或者在某一块功能上新增一些需求的时候&#xff0c;在没有国际化功能的页面中&#xff0c;我们随便复制一些文本&#xff0c;然后在vs code中全局搜索&#xff0c;很快就可以找到所要更改的代码文件在哪里&…...

C# OpenCvSharp 部署MOWA:多合一图像扭曲模型

目录 说明 效果 项目 代码 下载 参考 C# OpenCvSharp 部署MOWA&#xff1a;多合一图像扭曲模型 说明 算法模型的paper名称是《MOWA: Multiple-in-One Image Warping Model》 ariv链接 https://arxiv.org/pdf/2404.10716 效果 Stitched Image 翻译成中文意思是&…...

本地部署DeepSeek-R1模型(新手保姆教程)

背景 最近deepseek太火了&#xff0c;无数的媒体都在报道&#xff0c;很多人争相着想本地部署试验一下。本文就简单教学一下&#xff0c;怎么本地部署。 首先大家要知道&#xff0c;使用deepseek有三种方式&#xff1a; 1.网页端或者是手机app直接使用 2.使用代码调用API …...

神经网络常见激活函数 5-PReLU函数

文章目录 PReLU函数导函数函数和导函数图像优缺点pytorch中的PReLU函数tensorflow 中的PReLU函数 PReLU 参数化修正线性单元:Parametric ReLU 函数导函数 PReLU函数 P R e L U { x x > 0 α x x < 0 ( α 是可训练参数 ) \rm PReLU \left\{ \begin{array}{} x \qua…...

2025我的第二次社招,写在春招之季

先说一个好消息&#xff0c;C那些事 4w star了&#xff01; 前面断更了一个月&#xff0c;本篇文章就可以看到原因&#xff0c;哈哈。 大家好&#xff0c;我叫光城&#xff0c;腾讯实习转正做后端开发&#xff0c;后去小公司做数据库内核&#xff0c;经过这几年的成长与积累&am…...

Visual Studio Code中文出现黄色框子的解决办法

Visual Studio Code中文出现黄色框子的解决办法 一、vsCode中文出现黄色框子-如图二、解决办法 一、vsCode中文出现黄色框子-如图 二、解决办法 点击 “文件”点击 “首选项”点击 “设置” 搜索框直接搜索unicode选择“文本编辑器”&#xff0c;往下滑动&#xff0c;找到“Un…...

threejs开源代码之-旋转的彩色立方体

效果&#xff1a;旋转的彩色立方体 效果描述&#xff1a; 一个立方体在场景中旋转。立方体的每个面有不同的颜色。使用自定义着色器为立方体添加动态的光影效果。 代码实现 import * as THREE from three; import { OrbitControls } from three/examples/jsm/controls/OrbitC…...

visual studio 2008的试用版评估期已结束的解决办法

visual studio 2008试用期过了后&#xff0c;再次启动时提示&#xff1a;visual studio的试用版评估期已结束。 需要的工具&#xff1a;补丁文件PatchVS2008.exe 解决办法&#xff1a; 1.在“控制面板”-“添加删除程序”中选择visual studio 2008&#xff0c;点击“更改/卸载”…...

解锁 DeepSeek 模型高效部署密码:蓝耘平台深度剖析与实战应用

&#x1f496;亲爱的朋友们&#xff0c;热烈欢迎来到 青云交的博客&#xff01;能与诸位在此相逢&#xff0c;我倍感荣幸。在这飞速更迭的时代&#xff0c;我们都渴望一方心灵净土&#xff0c;而 我的博客 正是这样温暖的所在。这里为你呈上趣味与实用兼具的知识&#xff0c;也…...

Http和Socks的区别?

HTTP 和 SOCKS 的区别 HTTP 和 SOCKS 都是用于网络通信的协议&#xff0c;但它们在工作原理、应用场景和实现方式上有显著的区别。以下是详细的对比和说明。 一、HTTP 协议 1. 定义 HTTP&#xff08;HyperText Transfer Protocol&#xff09;是用于传输超文本数据的应用层协…...

VC播放mp3的方法

1、使用msi库 #include <mmsystem.h> #pragma comment(lib,"winmm.lib") .......//打开文件MCI_OPEN_PARMS mciOpen; mciOpen.lpstrDeviceType _T("mpegvideo"); mciOpen.lpstrElementName _T("c://1.mp3"); MCIERROR mciError mci…...

Docker 部署 verdaccio 搭建 npm 私服

一、镜像获取 # 获取 verdaccio 镜像 docker pull verdaccio/verdaccio 二、修改配置文件 cd /wwwroot/opt/docker/verdaccio/conf vim config.yaml config.yaml 配置文件如下&#xff0c;可以根据自己的需要进行修改 # # This is the default configuration file. It all…...

49-拓展(1)

49-拓展&#xff08;1&#xff09; 扩展概述 扩展可以为在当前 package 可见的类型&#xff08;除函数、元组、接口&#xff09;添加新功能。 当不能破坏被扩展类型的封装性&#xff0c;但希望添加额外的功能时&#xff0c;可以使用扩展。 可以添加的功能包括&#xff1a; …...

国产编辑器EverEdit - 在文件中查找和替换

1 在文件中查找和替换 1.1 应用场景 某些场景&#xff0c;用户需要在所有工程文件中进行查找和替换关键词&#xff0c;比如&#xff1a;查找工程中哪些文件使用了某个常量。 1.2 使用方法 选择主菜单查找 -> 在文件中查找和替换&#xff0c;或使用快捷键Ctrl Shift F&a…...

安全行业大模型SecLLM技术白皮书

在ChatGPT 呈现全球现象级热度时&#xff0c;通用大语言模型&#xff08;Large Language Model, LLM&#xff09;技术成为了推动创新和变革的关键驱动力。但由于安全行业的特殊性和复杂性&#xff0c;LLM 并不能满足其应用需求。安全行业大模型(Security Large Language Model,…...

基础入门-HTTP数据包红蓝队研判自定义构造请求方法请求头修改状态码判断

知识点&#xff1a; 1、请求头&返回包-方法&头修改&状态码等 2、数据包分析-红队攻击工具&蓝队流量研判 3、数据包构造-Reqable自定义添加修改请求 一、演示案例-请求头&返回包-方法&头修改&状态码等 数据包 客户端请求Request 请求方法 …...

2025年日祭

本文将同步发表于洛谷&#xff08;暂无法访问&#xff09;、CSDN 与 Github 个人博客&#xff08;暂未发布&#xff09; 本蒟自2025.2.8开始半停课。 任务计划&#xff08;站外题与专题&#xff09; 数了一下&#xff0c;通过人数比较高的题&#xff0c;也就是我准备补的题&a…...

git命令行删除远程分支、删除远程提交日志

目录 1、从本地通过命令行删除远程git分支2、删除已 commit 并 push 的记录 1、从本地通过命令行删除远程git分支 git push origin --delete feature/feature_xxx 删除远程分支 feature/feature_xxx 2、删除已 commit 并 push 的记录 git reset --hard 7b5d01xxxxxxxxxx 恢复到…...

centOS8安装MySQL8设置开机自动启动失败

提供一个终极解决方案虽然systemctl 更符合管理预期但是不能用 使用一下命令 修改配置文件、修改mysql.service全是问题 systemctl start mysqld systemctl enable mysqld systemctl daemon-reload完全不生效各种报错 提示配置文件内容有问题 Main process exited, codeexite…...

对接DeepSeek

其实&#xff0c;整个对接过程很简单&#xff0c;就四步&#xff0c;获取key&#xff0c;找到接口文档&#xff0c;接口测试&#xff0c;代码对接。 获取 KEY https://platform.deepseek.com/transactions 直接付款就是了&#xff08;现在官网暂停充值2025年2月7日&#xff0…...

SpringSecurity高级用法

SpringSecurity的高级用法&#xff0c;包括自定义loginUrl携带参数&#xff0c;自定义认证校验逻辑&#xff0c;自定义权限校验逻辑。 示例项目 https://github.com/qihaiyan/springcamp/tree/master/spring-advanced-security 一、概述 在项目实际开发过程中&#xff0c;Spr…...

NLP_[2]-认识文本预处理

文章目录 1 认识文本预处理1 文本预处理及其作用2. 文本预处理中包含的主要环节2.1 文本处理的基本方法2.2 文本张量表示方法2.3 文本语料的数据分析2.4 文本特征处理2.5数据增强方法2.6 重要说明 2 文本处理的基本方法1. 什么是分词2 什么是命名实体识别3 什么是词性标注 1 认…...