codeforce Round 935 div3 个人题解(A~F)

A. Setting up Camp

时间限制:每个测试1秒
内存限制:每个测试256兆字节
输入:标准输入
输出:标准输出

组委会计划在游览结束后带领奥林匹克运动会的参赛选手进行徒步旅行。目前,正在计算需要搭帐篷的数量。已知每顶帐篷最多可容纳3人。

在参赛选手中,有a个内向型,b个外向型和c个综合型:

  • 每个内向的人都想独自住在帐篷里。因此,内向者的帐篷里必须只有一个人–只有内向者自己。
  • 每个外向者都希望与另外两个人住在一个帐篷里。因此,一个外向者的帐篷里必须正好有三个人。
  • 每个综合型可以接受任何方式(独居、与一人同住或与两人同住)。
    组委会非常尊重每位参赛者的意愿,因此他们希望满足所有参赛者的愿望。

告诉我们至少需要多少顶帐篷,以满足所有参赛者的愿望。如果无法满足,则输出-1。

输入

每个测试包含多个测试用例。第一行包含一个整数t(1≤t≤104)–测试用例的数量。接下来是测试用例的描述。

每个测试用例由一行描述,其中包含三个整数a、b、c(0≤a,b,c≤109)–分别是内向型、外向型和综合型的数量。

输出

对于每个测试用例,输出一个整数–最少需要的帐篷数,如果无法容纳参赛者,则输出-1。

示例1

输入
10
1 2 3
1 4 1
1 4 2
1 1 1
1 3 2
19 7 18
0 0 0
7 0 0
0 24 0
1000000000 1000000000 1000000000
输出
3
-1
3
-1
3
28
0
7
8
1666666667

说明

在第一个测试用例中,1顶帐篷将分配给内向者,1顶帐篷将由两名外向者和一名综合型共享,最后一顶帐篷将由两名综合型共享。总共需要3顶帐篷。

在第二个测试用例中,三个外向者将使用1个帐篷,1个帐篷将由一个内向者使用。然后,剩下一个外向者和一个综合型。这个外向者将无法与另外两个人一起生活。

解题思路

a一人一顶,b三人一顶,剩下的人和c进行组合,如果总人数小于3则无法组合。

题解

#define _CRT_SECURE_NO_WARNINGS 1
 
#include <iostream>
#include <vector>
#include <algorithm>
#include <set>
#include <unordered_map>
#include <cstring>
#include <string>
#include <queue>
#include <stack>
#include <map>
#include <list>
#include <bitset>
#include <cmath>
 
#define endl '\n'
 
#define ft first
#define sd second
 
#define yes std::cout<<"Yes\n"
#define no std::cout<<"No\n"
 
 
using namespace std;
 
typedef long long ll;
typedef unsigned long long ull;
 
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef pair<string, string> pss;
typedef pair<string, int> psi;
typedef pair<string, ll> psl;
 
typedef vector<bool> vb;
typedef vector<int> vi;
typedef vector<ll> vl;
typedef vector<string> vs;
typedef vector<pii> vpii;
typedef vector<pll> vpll;
typedef vector<pss> vpss;
 
typedef vector<vi> vvi;
typedef vector<vl> vvl;
 
typedef queue <int> qi;
typedef queue <ll> ql;
typedef queue <pii> qpii;
typedef queue <pll> qpll;
typedef queue <psi> qpsi;
typedef queue <psl> qpsl;
 
typedef priority_queue<int> pqi;
typedef priority_queue<ll> pql;
typedef priority_queue<string> pqs;
typedef priority_queue<pii> pqpii;
typedef priority_queue<psi> pqpsi;
typedef priority_queue<pll> pqpl;
typedef priority_queue<psi> pqpsl;
 
typedef map<int, int> mii;
typedef map<ll, ll> mll;
typedef map<char, int> mci;
typedef map<char, ll> mcl;
typedef map<string, int> msi;
typedef map<string, ll> msl;
 
typedef unordered_map<int, int> umii;
typedef unordered_map<ll, ll> uml;
typedef unordered_map<char, int> umci;
typedef unordered_map<char, ll> umcl;
typedef unordered_map<string, int> umsi;
typedef unordered_map<string, ll> umsl;
 
 
void cinv(vi vec, int n)
{
    for (int i = 1; i <= (n); i++)
        cin >> (vec)[i];
}
void rcinv(vi vec, int n)
{
    for (int i = (n); i >= 1; i--)
        cin >> (vec)[i];
}
void coutv(vi vec, int n)
{
    for (int i = 1; i <= (n); i++)
        cout << (vec)[i] << " ";
    cout << '\n';
}
void rcoutv(vi vec, int n)
{
    for (int i = (n); i >= 1; i--)
        cout << (vec)[i] << " ";
    cout << '\n';
}
 
 
void solve()
{
    int a, b, c;
    cin >> a>>b>>c;
    int cnt = a + (b + c + 2) / 3;
    if (b % 3 != 0 && c + b % 3 < 3)
        cnt = -1;
    cout << cnt << endl;
}
 
int main()
{
    ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
    int t = 1;
    cin >> t;
    while (t--)
    {
        solve();
    }
    return 0;
}

B. Fireworks

时间限制:每个测试 1 1 1
内存限制:每个测试 256 256 256兆字节
输入:标准输入
输出:标准输出

徒步旅行的其中一天恰逢节假日,因此决定晚上在营地安排一场节日焰火表演。为此,徒步旅行的组织者购买了两个烟花发射装置和大量的发射炮弹。

两个装置同时开启。第一个装置每隔 a a a分钟(即发射后 a , 2 ⋅ a , 3 ⋅ a , … a,2⋅a,3⋅a,\dots a,2a,3a,分钟)发射一次烟花。第二个装置每 b b b分钟(即发射后 b , 2 ⋅ b , 3 ⋅ b , … b,2⋅b,3⋅b,\dots b,2b,3b,分钟)发射一次烟花。

每个烟花在发射后的 m + 1 m+1 m+1分钟内都可以在天空中看到,也就是说,如果一个烟花是在装置开启后的 x x x分钟后发射的,那么从 x x x x + m x+m x+m(包括首尾两分钟)的每一分钟都可以看到该烟花。如果一个烟花在另一个烟花 m m m
分钟后发射,则两个烟花都将在一分钟内可见。

天空中最多可以同时看到多少枚烟花?

输入

每个测试包含多个测试用例。第一行包含一个整数 t t t 1 ≤ t ≤ 1 0 4 1≤t≤10^4 1t104)–测试用例的数量。接下来是测试用例的说明。

每个测试用例的第一行也是唯一一行包含整数 a a a b b b m m m( 1 ≤ a , b , m ≤ 1 0 18 1≤a,b,m≤10^{18} 1a,b,m1018)–第一次安装、第二次安装的发射频率,以及烟花在天空中可见的时间。

输出

对于每组输入数据,输出一个数字–可同时看到的最大烟花数量。

示例1

输入
6
6 7 4
3 4 10
7 8 56
5 6 78123459896
1 1 1
1 1 1000000000000000000
输出
2
7
17
28645268630
4
2000000000000000002

说明

在第一组输入数据中,烟花在天空中的可见时间为 5 5 5分钟。由于第一个装置每 6 6 6分钟发射一次烟花,第二个装置每 7 7 7分钟发射一次烟花,因此同一装置发射的两个烟花不会同时出现在天空中。同时,在节日开始 7 7 7分钟后,从第一个营地和第二个营地各发射一个烟花。因此,可以同时看到的烟花不会超过 2 2 2个。

在第三组输入数据中, 112 112 112分钟后可以看到 17 17 17个烟花:

烟花从第一个装置发射的时间为 [ 56 , 63 , 70 , 77 , 84 , 91 , 98 , 105 , 112 ] [ 56,63,70,77,84,91,98,105,112 ] [56,63,70,77,84,91,98,105,112]
[ 56 , 64 , 72 , 80 , 88 , 96 , 104 , 112 ] [ 56,64,72,80,88,96,104,112 ] [56,64,72,80,88,96,104,112]时从第二个装置发射的烟花。

解题思路

照亮时间除以发射间隔即一个装置最多同时存在的烟花数量,由于发射时也算同时存在,所以要额外加2。

题解

#define _CRT_SECURE_NO_WARNINGS 1

#include <iostream>
#include <vector>
#include <algorithm>
#include <set>
#include <unordered_map>
#include <string>
#include <queue>
#include <stack>
#include <map>
#include <list>
#include <bitset>
#include <cmath>

#define endl '\n'

#define ft first
#define sd second

#define yes std::cout<<"Yes\n"
#define no std::cout<<"No\n"


using namespace std;

typedef long long ll;
typedef unsigned long long ull;

typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef pair<string, string> pss;
typedef pair<string, int> psi;
typedef pair<string, ll> psl;

typedef vector<bool> vb;
typedef vector<int> vi;
typedef vector<ll> vl;
typedef vector<string> vs;
typedef vector<pii> vpii;
typedef vector<pll> vpll;
typedef vector<pss> vpss;

typedef vector<vi> vvi;
typedef vector<vl> vvl;

typedef queue <int> qi;
typedef queue <ll> ql;
typedef queue <pii> qpii;
typedef queue <pll> qpll;
typedef queue <psi> qpsi;
typedef queue <psl> qpsl;

typedef priority_queue<int> pqi;
typedef priority_queue<ll> pql;
typedef priority_queue<string> pqs;
typedef priority_queue<pii> pqpii;
typedef priority_queue<psi> pqpsi;
typedef priority_queue<pll> pqpl;
typedef priority_queue<psi> pqpsl;

typedef map<int, int> mii;
typedef map<ll, ll> mll;
typedef map<char, int> mci;
typedef map<char, ll> mcl;
typedef map<string, int> msi;
typedef map<string, ll> msl;

typedef unordered_map<int, int> umii;
typedef unordered_map<ll, ll> uml;
typedef unordered_map<char, int> umci;
typedef unordered_map<char, ll> umcl;
typedef unordered_map<string, int> umsi;
typedef unordered_map<string, ll> umsl;


void cinv(vi vec,int n) 
{
    for (int i = 1; i <= (n); i++)
        cin >> (vec)[i];
}
void rcinv(vi vec, int n)
{
    for (int i = (n); i >= 1; i--)
        cin >> (vec)[i];
}
void coutv(vi vec, int n) 
{
    for (int i = 1; i <= (n); i++)
        cout << (vec)[i] << " ";
    cout << '\n'; 
}
void rcoutv(vi vec, int n)
{ 
    for (int i = (n); i >= 1; i--)
        cout << (vec)[i] << " ";
    cout << '\n'; 
}


void solve()
{
    int a,b,m;
    cin>>a>>b>>m;
    int temp=2;
    temp+=m/b;
    temp+=m/a;
    cout<<temp<<endl;
}

int main()
{
	ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
	int t = 1;
	cin >> t;
	while (t--)
	{
		solve();
	}
	return 0;
}

C. Left and Right Houses

时间限制:每个测试 2 2 2
内存限制:每个测试 256 256 256兆字节
输入:标准输入
输出:标准输出

在莱托沃村有 n n n栋房子。村民们决定修建一条大路,将村子分为左右两边。每个居民都想住在街道的右侧或左侧,这可以用序列 a 1 , a 2 , … , a n a_1,a_2,\dots,a_n a1,a2,,an来描述,其中 a j = 0 a_j=0 aj=0如果 j j jth房子的居民想住在街道的左侧;否则, a j = 1 a_j=1 aj=1

道路将从两栋房子之间穿过。它左边的房子将被宣布为左侧,右边的房子将被宣布为右侧。更正式地说,让道路从房屋 i i i i + 1 i+1 i+1之间通过。那么位于 1 1 1 i i i之间的房子将位于街道的左侧,位于 i + 1 i+1 i+1 n n n之间的房子将位于街道的右侧。道路也可以经过第一栋房屋之前和最后一栋房屋之后;在这种情况下,整个村庄分别被宣布为右侧或左侧。

为了使设计公平,我们决定在铺设道路时,至少要让村子两边各一半的居民对选择感到满意。也就是说,在一侧的 x x x个居民中,至少有 ⌈ x 2 ⌉ \lceil\frac{x}{2}\rceil 2x个居民愿意住在这一侧,其中 ⌈ x ⌉ \lceil x\rceil x表示四舍五入的实数 x x x

在路的左边,会有 i i i座房子,在相应的 a j a_j aj中,至少要有 ⌈ i 2 ⌉ \lceil\frac{i}{2}\rceil 2i个零。路的右边有 n − i n-i ni座房子,在相应的 a j a_j aj中至少要有 ⌈ n − i 2 ⌉ \lceil\frac{n-i}{2}\rceil 2ni个一。

确定在哪座房子 i i i之后铺设道路,以满足所述条件,并尽可能靠近村庄中央。从形式上看,在所有合适的位置 i i i中,尽量减少 ∣ n / 2 − i ∣ |n/2-i| n/2i

如果有多个合适的位置 i i i,输出较小的一个。

输入

每个测试包含多个测试用例。第一行包含测试用例的数量 t t t( 1 ≤ t ≤ 2 ⋅ 1 0 4 1≤t≤2⋅10^4 1t2104)。测试用例说明如下。

每个测试用例的第一行包含一个整数 n n n( 3 ≤ n ≤ 3 ⋅ 1 0 5 3≤n≤3⋅10^5 3n3105)。每个测试用例的下一行包含一个长度为 n n n的字符串 a a a,该字符串仅由 0 0 0 1 1 1组成。

保证所有测试用例中 n n n的总和不超过 3 ⋅ 1 0 5 3⋅10^5 3105

输出

对于每个测试用例,输出一个数字 i i i–道路应该铺设在房屋之后的位置(如果道路应该铺设在第一栋房屋之前,则输出 0 0 0)。我们可以证明答案总是存在的。

示例1

输入
7
3
101
6
010111
6
011001
3
000
3
110
3
001
4
1100
输出
2
3
2
3
0
1
0

说明

让我们来看第一个输入数据的例子。

如果我们在第一栋房屋后铺设道路,那么街道左侧将有一栋房屋 a 1 = 1 a_1=1 a1=1,其居民希望住在街道右侧。那么在偶数边上的 1 1 1户居民中, 0 0 0户居民会对这一选择感到满意,这意味着道路不能铺设在 1 1 1户之后。

如果我们在第二栋房屋后铺设道路,左侧 2 2 2户居民中的 1 1 1户(偏好 a 1 = 1 a_1=1 a1=1 a 2 = 0 a_2=0 a2=0)和右侧 1 1 1户居民中的 1 1 1户(偏好 a 3 = 1 a_3=1 a3=1)将对选择感到满意。两边各有一半以上的居民对选择感到满意,这意味着道路可以铺设在房屋 2 2 2之后。我们可以证明这是最优答案。

解题思路

使用前缀和数组存储每个区间 1 1 1的数量,然后判断 1 1 1 0 0 0是否符合条件即可。注意,房子为奇数个的时候村庄中心的坐标并非整数。

题解

#define _CRT_SECURE_NO_WARNINGS 1

#include <iostream>
#include <vector>
#include <algorithm>
#include <set>
#include <unordered_map>
#include <cstring>
#include <string>
#include <queue>
#include <stack>
#include <map>
#include <list>
#include <bitset>
#include <cmath>

#define endl '\n'

#define ft first
#define sd second

#define yes std::cout<<"Yes\n"
#define no std::cout<<"No\n"


using namespace std;

typedef long long ll;
typedef unsigned long long ull;

typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef pair<string, string> pss;
typedef pair<string, int> psi;
typedef pair<string, ll> psl;

typedef vector<bool> vb;
typedef vector<int> vi;
typedef vector<ll> vl;
typedef vector<string> vs;
typedef vector<pii> vpii;
typedef vector<pll> vpll;
typedef vector<pss> vpss;

typedef vector<vi> vvi;
typedef vector<vl> vvl;

typedef queue <int> qi;
typedef queue <ll> ql;
typedef queue <pii> qpii;
typedef queue <pll> qpll;
typedef queue <psi> qpsi;
typedef queue <psl> qpsl;

typedef priority_queue<int> pqi;
typedef priority_queue<ll> pql;
typedef priority_queue<string> pqs;
typedef priority_queue<pii> pqpii;
typedef priority_queue<psi> pqpsi;
typedef priority_queue<pll> pqpl;
typedef priority_queue<psi> pqpsl;

typedef map<int, int> mii;
typedef map<ll, ll> mll;
typedef map<char, int> mci;
typedef map<char, ll> mcl;
typedef map<string, int> msi;
typedef map<string, ll> msl;

typedef unordered_map<int, int> umii;
typedef unordered_map<ll, ll> uml;
typedef unordered_map<char, int> umci;
typedef unordered_map<char, ll> umcl;
typedef unordered_map<string, int> umsi;
typedef unordered_map<string, ll> umsl;


void cinv(vi vec, int n)
{
    for (int i = 1; i <= (n); i++)
        cin >> (vec)[i];
}
void rcinv(vi vec, int n)
{
    for (int i = (n); i >= 1; i--)
        cin >> (vec)[i];
}
void coutv(vi vec, int n)
{
    for (int i = 1; i <= (n); i++)
        cout << (vec)[i] << " ";
    cout << '\n';
}
void rcoutv(vi vec, int n)
{
    for (int i = (n); i >= 1; i--)
        cout << (vec)[i] << " ";
    cout << '\n';
}


void solve()
{
    int n;
    cin >> n;
    string s;
    cin >> s;
    s = "0" + s;
    vi sums(n + 2);
    for (int i = 1; i <= n + 1; i++)
    {
        sums[i] = int(s[i] - '0') + sums[i - 1];
    }
    vi ans;
    for (int i = 0; i <= n; i++)
    {
        if (sums[i] <= (i - (i + 1) / 2) && (sums[n] - sums[i]) >= ((n - i + 1) / 2))
            ans.push_back(i);
    }
    int res = ans[0];
    double mid = double(n) / 2.0;
    for (int i = 1; i < ans.size(); i++)
    {
        if (abs(double(ans[i]) - mid) < abs(double(res) - mid))
            res = ans[i];
    }
    cout << res << endl;;
}


int main()
{
    ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
    int t = 1;
    cin >> t;
    while (t--)
    {
        solve();
    }
    return 0;
}

D. Seraphim the Owl

时间限制:每个测试 2 2 2
内存限制:每个测试 256 256 256兆字节
输入:标准输入
输出:标准输出

大家排成 n n n号队,从 i = 1 i=1 i=1号开始,向猫头鹰谢拉菲姆请教生命的意义。不巧的是,基里尔正忙着为这个问题编写传说,所以他来得晚了一些,站在了 n n n号人之后的队尾。基里尔对这种情况完全不满意,于是他决定贿赂一些排在他前面的人。

对于队列中的第 i i ith人,基里尔知道两个值: a i a_i ai b i b_i bi。如果此刻基里尔站在位置 i i i上,那么他可以选择任意一个位置 j j j,比如 j < i j<i j<i,然后与位置 j j j上的人交换位置。在这种情况下,基里尔需要支付他 a j a_j aj个硬币。而对于 j < k < i j<k<i j<k<i的每一个 k k k,基里尔都要向位置 k k k的人支付 b k b_k bk个硬币。

基里尔很节俭,所以他想花尽可能少的硬币,但是他又不想等太久,所以基里尔认为他应该排在第一个 m m m人中。

请帮助基里尔确定,为了不等太久,他最少需要花费多少金币。

输入

每个测试由几组输入数据组成。第一行包含一个整数 t t t( 1 ≤ t ≤ 104 1≤t≤104 1t104) - 测试用例的数量。然后是测试用例的描述。

每个测试用例的第一行包含两个整数 n n n m m m( 1 ≤ m ≤ n ≤ 200000 1≤m≤n≤200000 1mn200000)–分别是除基里尔外排队人数和基里尔最终位置的最大允许值。

第二行包含 n n n个整数 a 1 , a 2 , … , a n a_1,a_2,…,a_n a1,a2,,an,中间用空格隔开( 1 ≤ a i ≤ 1 0 9 1≤a_i≤10^9 1ai109)。

第三行包含 n n n个整数 b 1 , b 2 , … , b n b_1,b_2,…,b_n b1,b2,,bn,用空格隔开( 1 ≤ b i ≤ 1 0 9 1≤b_i≤10^9 1bi109)。

保证所有测试用例中 n n n的值之和不超过 2 ⋅ 1 0 5 2⋅10^5 2105

输出

对于每个测试用例,输出一个整数 - Kirill 需要花费的最少金币数。

示例1

输入
4
4 2
7 3 6 9
4 3 8 5
6 2
6 9 7 1 8 3
5 8 8 1 4 1
7 7
7 2 9 2 6 5 9
9 1 10 7 1 4 9
2 1
2 3
1 1
输出
14
22
9
3

解题思路

为了找到最少花费的金币数,从队伍的末尾开始向前遍历。对于每个位置 i i i,我们计算排在第 i i i 个人后面的所有人中的最小 m − i m-i mi 个人的金币花费之和,并加上排在第 i i i 个人前面的人与他交换位置所需的金币数。在遍历中不断更新最小金币花费数。

题解

#define _CRT_SECURE_NO_WARNINGS 1

#include <iostream>
#include <vector>
#include <algorithm>
#include <set>
#include <unordered_map>
#include <string>
#include <queue>
#include <stack>
#include <map>
#include <list>
#include <bitset>
#include <cmath>

#define endl '\n'

#define ft first
#define sd second

#define yes std::cout<<"Yes\n"
#define no std::cout<<"No\n"


using namespace std;

typedef long long ll;
typedef unsigned long long ull;

typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef pair<string, string> pss;
typedef pair<string, int> psi;
typedef pair<string, ll> psl;

typedef vector<bool> vb;
typedef vector<int> vi;
typedef vector<ll> vl;
typedef vector<string> vs;
typedef vector<pii> vpii;
typedef vector<pll> vpll;
typedef vector<pss> vpss;

typedef vector<vi> vvi;
typedef vector<vl> vvl;

typedef queue <int> qi;
typedef queue <ll> ql;
typedef queue <pii> qpii;
typedef queue <pll> qpll;
typedef queue <psi> qpsi;
typedef queue <psl> qpsl;

typedef priority_queue<int> pqi;
typedef priority_queue<ll> pql;
typedef priority_queue<string> pqs;
typedef priority_queue<pii> pqpii;
typedef priority_queue<psi> pqpsi;
typedef priority_queue<pll> pqpl;
typedef priority_queue<psi> pqpsl;

typedef map<int, int> mii;
typedef map<ll, ll> mll;
typedef map<char, int> mci;
typedef map<char, ll> mcl;
typedef map<string, int> msi;
typedef map<string, ll> msl;

typedef unordered_map<int, int> umii;
typedef unordered_map<ll, ll> uml;
typedef unordered_map<char, int> umci;
typedef unordered_map<char, ll> umcl;
typedef unordered_map<string, int> umsi;
typedef unordered_map<string, ll> umsl;


void cinv(vi vec, int n)
{
    for (int i = 1; i <= (n); i++)
        cin >> (vec)[i];
}
void rcinv(vi vec, int n)
{
    for (int i = (n); i >= 1; i--)
        cin >> (vec)[i];
}
void coutv(vi vec, int n)
{
    for (int i = 1; i <= (n); i++)
        cout << (vec)[i] << " ";
    cout << '\n';
}
void rcoutv(vi vec, int n)
{
    for (int i = (n); i >= 1; i--)
        cout << (vec)[i] << " ";
    cout << '\n';
}


void solve()
{
    ll n, m;
    cin >> n >> m;
    vl a(n);
    vl b(n);
    for (int i = 0; i < n; i++)
    {
        cin >> a[i];
    }
    for (int i = 0; i < n; i++)
    {
        cin >> b[i];
    }
    ll s = 0;
    ll ans = INT64_MAX;
    for (int i = n - 1; i >= 0; i--)
    {
        if (i + 1 <= m)
        {
            ans = min(ans, s + a[i]);
        }
        s += min(a[i], b[i]);
    }
    cout << ans << endl;
}

int main()
{
    ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
    int t = 1;
    cin >> t;
    while (t--)
    {
        solve();
    }
    return 0;
}

E. Binary Search

时间限制:每个测试 2 2 2
内存限制:每个测试 256 256 256兆字节
输入:标准输入
输出:标准输出

安东在徒步旅行中感到无聊,想解决一些问题。他问基里尔有没有新问题,基里尔当然有。

给你一个大小为 n n n的排列数 p p p和一个需要求出的数字 x x x。长度为 n n n的排列是由 n n n个不同的整数组成的数组,这些整数从 1 1 1 n n n依次排列。例如, [ 2 , 3 , 1 , 5 , 4 ] [2,3,1,5,4] [2,3,1,5,4]是一个排列数组,但 [ 1 , 2 , 2 ] [1,2,2] [1,2,2]不是排列数组( 2 2 2在数组中出现了两次), [ 1 , 3 , 4 ] [1,3,4] [1,3,4]也不是排列数组( n = 3 n=3 n=3但数组中有 4 4 4)。

你认为自己是一个很酷的程序员,所以你将使用一种高级算法进行搜索–二分查找。但是,你忘了二分查找必须对数组进行排序。

为了得到正确的答案,你可以在运行算法之前执行以下操作不超过 2 2 2次:选择索引 i i i j j j( 1 ≤ i , j ≤ n 1≤i,j≤n 1i,jn)并交换位置 i i i j j j上的元素。

然后,执行二分查找。在算法开始时,声明两个变量 l = 1 l=1 l=1 r = n + 1 r=n+1 r=n+1。然后执行下面的循环:

  • 如果 r − l = 1 r-l=1 rl=1,结束循环
  • m = ⌊ r + l 2 ⌋ m=\left\lfloor\frac{r+l}{2}\right\rfloor m=2r+l
  • 如果 p m ≤ x p_m\leq x pmx,赋值 l = m l=m l=m,否则 r = m r=m r=m

我们的目标是在算法之前重新排列排列组合中的数字,以便在算法执行之后, p l p_l pl等于 x x x。可以证明 2 2 2操作总是足够的。

输入

每个测试由多个测试用例组成。第一行包含一个整数 t t t( 1 ≤ t ≤ 2 ⋅ 1 0 4 1≤t≤2⋅10^4 1t2104) - 测试用例的数量。然后是测试用例的说明。

每个测试用例的第一行包含两个整数 n n n x x x( 1 ≤ x ≤ n ≤ 2 ⋅ 1 0 5 1≤x≤n≤2⋅10^5 1xn2105)–排列的长度和要找到的数字。

第二行包含由空格分隔的排列 p p p( 1 ≤ p i ≤ n 1≤p_i≤n 1pin)。

保证所有测试用例的 n n n值之和不超过 2 ⋅ 1 0 5 2⋅10^5 2105

输出

对于每个测试用例,在第一行输出一个整数 k k k( 0 ≤ k ≤ 2 0≤k≤2 0k2) - 您执行的操作数。在接下来的 k k k行中,输出 2 2 2个整数 i i i j j j( 1 ≤ i , j ≤ n 1≤i,j≤n 1i,jn) 用空格隔开,表示正在交换位置 i i i j j j的元素。

请注意,您不需要尽量减少操作次数。

示例

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

解题思路

先将 x x x放在边界上,然后不断循环二分,直到终止在某一位置,然后将在边界上的 x x x与这个位置互换。由于 x x x存放在边界上,所以不会影响二分的循环。

题解

#define _CRT_SECURE_NO_WARNINGS 1

#include <iostream>
#include <vector>
#include <algorithm>
#include <set>
#include <unordered_map>
#include <cstring>
#include <string>
#include <queue>
#include <stack>
#include <map>
#include <list>
#include <bitset>
#include <cmath>

#define endl '\n'

#define ft first
#define sd second

#define yes std::cout<<"Yes\n"
#define no std::cout<<"No\n"


using namespace std;

typedef long long ll;
typedef unsigned long long ull;

typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef pair<string, string> pss;
typedef pair<string, int> psi;
typedef pair<string, ll> psl;

typedef vector<bool> vb;
typedef vector<int> vi;
typedef vector<ll> vl;
typedef vector<string> vs;
typedef vector<pii> vpii;
typedef vector<pll> vpll;
typedef vector<pss> vpss;

typedef vector<vi> vvi;
typedef vector<vl> vvl;

typedef queue <int> qi;
typedef queue <ll> ql;
typedef queue <pii> qpii;
typedef queue <pll> qpll;
typedef queue <psi> qpsi;
typedef queue <psl> qpsl;

typedef priority_queue<int> pqi;
typedef priority_queue<ll> pql;
typedef priority_queue<string> pqs;
typedef priority_queue<pii> pqpii;
typedef priority_queue<psi> pqpsi;
typedef priority_queue<pll> pqpl;
typedef priority_queue<psi> pqpsl;

typedef map<int, int> mii;
typedef map<ll, ll> mll;
typedef map<char, int> mci;
typedef map<char, ll> mcl;
typedef map<string, int> msi;
typedef map<string, ll> msl;

typedef unordered_map<int, int> umii;
typedef unordered_map<ll, ll> uml;
typedef unordered_map<char, int> umci;
typedef unordered_map<char, ll> umcl;
typedef unordered_map<string, int> umsi;
typedef unordered_map<string, ll> umsl;


void cinv(vi vec, int n)
{
    for (int i = 1; i <= (n); i++)
        cin >> (vec)[i];
}
void rcinv(vi vec, int n)
{
    for (int i = (n); i >= 1; i--)
        cin >> (vec)[i];
}
void coutv(vi vec, int n)
{
    for (int i = 1; i <= (n); i++)
        cout << (vec)[i] << " ";
    cout << '\n';
}
void rcoutv(vi vec, int n)
{
    for (int i = (n); i >= 1; i--)
        cout << (vec)[i] << " ";
    cout << '\n';
}


void solve()
{
    int n, x;
    cin >> n >> x;
    vi a(n);
    int loc = 0;
    for (int i = 0; i < n; i++)
    {
        cin >> a[i];
        if (a[i] == x)
            loc = i + 1;
    }
    int l = 0;
    int r = n;
    int cnt = 0;
    vpii ans;
    if (loc != n) 
    {
        cnt++;
        swap(a[loc - 1], a[n - 1]);
        ans.push_back({ loc, n });
    }
    while ((r - l) > 1)
    {
        int m = (r + l) / 2;
        if (a[m] <= x)
            l = m;
        else
            r = m;
    }
    if (l != n - 1)
    {
        cnt++;
        ans.push_back({ l + 1, n });
    }

    cout << cnt << endl;
    for (int i = 0; i < cnt; i++) 
    {
        cout << ans[i].first << " " << ans[i].second<<endl;
    }
}

int main()
{
    ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
    int t = 1;
    cin >> t;
    while (t--)
    {
        solve();
    }
    return 0;
}

F. Kirill and Mushrooms

时间限制:每次测试 2 2 2
内存限制:每次测试 256 256 256兆字节
输入:标准输入
输出:标准输出

营地里的人一睡着,基里尔就偷偷溜出帐篷,去智者橡树那里采蘑菇。

众所周知,橡树下生长着 n n n种蘑菇,每种蘑菇都有魔力 v i v_i vi。基里尔非常想用这些蘑菇制作一种魔力最大的灵药。

灵药的强度等于其中蘑菇的数量与这些蘑菇中最小魔力的乘积。为了配制灵药,基里尔将依次采摘生长在橡树下的蘑菇。基里尔可以按照任何顺序采集蘑菇。

然而,事情并非如此简单。智慧橡树告诉基里尔从 1 1 1 n n n的数字 p p p的排列组合。如果基里尔只采摘 k k k个蘑菇,那么所有指数为 p 1 , p 2 , … , p k − 1 p_1,p_2,…,p_{k-1} p1,p2,,pk1的蘑菇的魔力就会变成 0 0 0。基里尔不会使用魔力为零的蘑菇来配制灵药。

你的任务就是帮助基里尔采集蘑菇,使他能够酿造出最大魔力的灵药。不过,基里尔有点害怕在橡树附近逗留太久,所以在所有合适的采集蘑菇的选项中,他要求您找到蘑菇数量最少的那个。

长度为 n n n的排列是由 1 1 1 n n n n n n个不同整数按任意顺序组成的数组。例如, [ 2 , 3 , 1 , 5 , 4 ] [2,3,1,5,4] [2,3,1,5,4]是一个排列数组,但 [ 1 , 2 , 2 ] [1,2,2] [1,2,2]不是排列数组( 2 2 2在数组中出现两次), [ 1 , 3 , 4 ] [1,3,4] [1,3,4]也不是排列数组( n = 3 n=3 n=3,但 4 4 4在数组中出现)。

输入

每个测试由多个测试用例组成。第一行包含一个整数 t t t( 1 ≤ t ≤ 1 0 4 1≤t≤10^4 1t104) - 测试用例的个数。测试用例说明如下。

每个测试用例的第一行包含一个整数 n n n( 1 ≤ n ≤ 200000 1≤n≤200000 1n200000) - 蘑菇的数量。

第二行包含一个大小为 n n n( 1 ≤ v i ≤ 1 0 9 1≤v_i≤10^9 1vi109)的数组 v v v --蘑菇的数量。( 1 ≤ v i ≤ 1 0 9 1≤v_i≤10^9 1vi109) --蘑菇的魔力。

第三行包含一个从 1 1 1 n n n的数字排列 p p p

保证所有测试用例中 n n n的值之和不超过 2 ⋅ 1 0 5 2⋅10^5 2105

输出

对于每个测试用例,输出两个用空格隔开的整数–可酿造的灵药的最大浓度和基里尔为此需要使用的最少蘑菇数量。

示例

输入
6
3
9 8 14
3 2 1
5
1 2 3 4 5
1 2 3 4 5
6
1 2 3 4 5 6
6 5 4 3 2 1
5
1 4 6 10 10
2 1 4 5 3
4
2 2 5 5
4 2 3 1
5
1 2 9 10 10
1 4 2 3 5
输出
16 2
9 3
8 2
20 2
5 1
20 2
说明

在第一个例子中,您需要采摘指数为 1 1 1 2 2 2的蘑菇,因此灵药的魔力等于 2 ⋅ min ⁡ ( a 1 , a 2 ) = 2 ⋅ min ⁡ ( 9 , 8 ) = 2 ⋅ 8 = 16 2⋅\min(a_1,a_2)=2⋅\min(9,8)=2⋅8=16 2min(a1,a2)=2min(9,8)=28=16。注意,采摘两朵蘑菇后,指数为 3 3 3的蘑菇的魔力将变为 0 0 0

解题思路

p n p_n pn开始从后向前依次将 v p i v_{p_i} vpi添加进优先队列中(小的为高优先级),然后枚举每种情况就行。

题解

#define _CRT_SECURE_NO_WARNINGS 1

#include <iostream>
#include <vector>
#include <algorithm>
#include <set>
#include <unordered_map>
#include <string>
#include <queue>
#include <stack>
#include <map>
#include <list>
#include <bitset>
#include <cmath>

#define endl '\n'

#define ft first
#define sd second

#define yes std::cout<<"Yes\n"
#define no std::cout<<"No\n"


using namespace std;

typedef long long ll;
typedef unsigned long long ull;

typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef pair<string, string> pss;
typedef pair<string, int> psi;
typedef pair<string, ll> psl;

typedef vector<bool> vb;
typedef vector<int> vi;
typedef vector<ll> vl;
typedef vector<string> vs;
typedef vector<pii> vpii;
typedef vector<pll> vpll;
typedef vector<pss> vpss;

typedef vector<vi> vvi;
typedef vector<vl> vvl;

typedef queue <int> qi;
typedef queue <ll> ql;
typedef queue <pii> qpii;
typedef queue <pll> qpll;
typedef queue <psi> qpsi;
typedef queue <psl> qpsl;

typedef priority_queue<int> pqi;
typedef priority_queue<ll> pql;
typedef priority_queue<string> pqs;
typedef priority_queue<pii> pqpii;
typedef priority_queue<psi> pqpsi;
typedef priority_queue<pll> pqpl;
typedef priority_queue<psi> pqpsl;

typedef map<int, int> mii;
typedef map<ll, ll> mll;
typedef map<char, int> mci;
typedef map<char, ll> mcl;
typedef map<string, int> msi;
typedef map<string, ll> msl;

typedef unordered_map<int, int> umii;
typedef unordered_map<ll, ll> uml;
typedef unordered_map<char, int> umci;
typedef unordered_map<char, ll> umcl;
typedef unordered_map<string, int> umsi;
typedef unordered_map<string, ll> umsl;


void cinv(vi vec, int n)
{
    for (int i = 1; i <= (n); i++)
        cin >> (vec)[i];
}
void rcinv(vi vec, int n)
{
    for (int i = (n); i >= 1; i--)
        cin >> (vec)[i];
}
void coutv(vi vec, int n)
{
    for (int i = 1; i <= (n); i++)
        cout << (vec)[i] << " ";
    cout << '\n';
}
void rcoutv(vi vec, int n)
{
    for (int i = (n); i >= 1; i--)
        cout << (vec)[i] << " ";
    cout << '\n';
}


void solve()
{
    int n; cin >> n;
    vi v(n);
    vi p(n);
    for (int i = 0; i < n; i++)
    {
        cin >> v[i];
    }
    for (int i = 0; i < n; i++)
    {
        cin >> p[i];
        p[i]--;
    }
    priority_queue<int,vi,greater<int>> pq;
    ll ans = INT64_MIN;
    int num = 0;
    for (int i = n; i >= 1; i--)
    {
        pq.push(v[p[i - 1]]);
        while (pq.size() > i)
        {
            pq.pop();
        }
        if (pq.size() == i)
        {
            ll strength = (ll)i * pq.top();
            if ( strength> ans)
            {
                ans = strength;
                num = i;
            }
            else if (strength == ans)
            {
                num = min(num, i);
            }
        }
    }
    cout << ans << " " << num << endl;
}

int main()
{
    ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
    int t = 1;
    cin >> t;
    while (t--)
    {
        solve();
    }
    return 0;
}
  • 28
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值