Codeforces Round #529 (Div. 3)(全部题解)

A. Repeating Cipher

题意:

将一个字符串S的第一个字符写一次,第二个写两次,第三个写三次......得到字符串t,给你t,求S

分析:

根据规则,t的第一个,第二个,第四个,第七个,第十一个......便是S的组成

代码:

#include 
#include 
#include 
using namespace std;
int main()
{
    string s;
    int n;
    cin>>n>>s;
    int k = 0;
    for(int i=0;i

B. Array Stabilization

题意:

从数组中删除一个值,求数组中(最大-最小的值)最小是多少

分析:

要么删最大,要么删最小

代码:

#include 
#include 
#include 
using namespace std;
const int N = 2e5+55;
int a[N];
int main()
{
    int n;
    cin>>n;
    for(int i=0;i>a[i];
    sort(a,a+n);
    int b = a[n-1]-a[1];
    int c = a[n-2]-a[0];
    cout<

C. Powers Of Two

题意:

问一个数 n 能否分成k个2^x形式的数的和

分析:

观察n的二进制下有m个1,那么最少就需要m个,最多无非是n个1相加,k>m时就需要拆分,2^x = 2^(x-1)+2^(x-1),多了一个,所以只要k属于[m,n],就一定可以拆分成k个

代码:

#include 
#include 
#include 
#include 
using namespace std;
const int N = 2e5+55;
int a[N];
vector v;
int main()
{
    int n,k;
    cin>>n>>k;
    int sum1 = 0;
    for(int i=0; i<31; ++i)
    {
        if(n&(1<=sum1&&k<=n)
    {
        cout<<"YES"<1)
            {
                v[i] = v[i]/2;
                v.push_back(v[i]);
            }
            else i++;
        }
        for(int i=0; i

D. Circular Dance

题意:

n个人围成一圈,每个人记得他的后面两个人是谁,输出每个人站的位置

分析:

注意:不确定后面两个人顺序,ai_1不一定就挨着第i个人

代码:


#include 
#include 
#include 
#include 
using namespace std;
const int N = 2e5+55;
int p[N][2];
int vis[N];
void dfs(int x)
{
    if(!vis[x])
    {
        cout<>n;
    for(int i=1; i<=n; ++i)
        cin>>p[i][0]>>p[i][1];
    dfs(1);
    return 0;
}

E. Almost Regular Bracket Sequence

题意:

给你一串括号序列,你可以改变一个位置的括号使得序列合法,求有多少个这样的位置

分析:

用栈来去掉合法的序列,讨论最后栈里剩下的情况

代码:

#include 
#include 
#include 
#include 
#include 
using namespace std;
const int N = 1e6+66;
char ss[N];
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    stack s;
    int n;
    cin>>n;
    for(int i=1;i<=n;++i)
    {
        cin>>ss[i];
        if(ss[i]==')')
        {
            if(!s.empty()&&ss[s.top()]=='(') s.pop();
            else s.push(i);
        }
        else s.push(i);
    }
    if(s.size()==0||n%2||s.size()>2) cout<<0;//很显然
    else
    {
        int a = s.top();s.pop();
        int b = s.top();
        if(ss[b]==')')
        {
            if(ss[a]==')')  //b位置左边的)都可以改变
            {
                int ans = 0;
                for(int i=1;i<=b;++i)
                    if(ss[i]==')') ans++;
                cout<

F. Make It Connected

题意:

有n个点,每个点有一个权值,在两个点之间连一条边的花费为两点权值之和,还有m条特殊边,加入这条边的花费为w,问使图联通最少花费多少

分析:

使图联通且花费最少,无非是建一颗最小生成树,除了已知的m条边,我们还可以建n*(n-1)/2条边(每两个点一条边),但n很大,建了也存不下,考虑一个点和图联通,它的最小花费一定是和最小权值的点连一条边,于是我们就缩减到了n-1条边,克鲁斯卡尔跑一遍最小生成树就OK了

代码

#include 
#include 
#include 
#include 
#define mk make_pair
#define f first
#define s second
using namespace std;
typedef long long ll;
const int MAXN = 2e5+255;
struct node
{
    int u,v;
    ll w;
};
node e[MAXN<<1];  
pair p[MAXN];
bool cmp(pair p1,pair p2)
{
    return p1.s>n>>m;
    for(int i=1;i<=n;++i)
    {
        cin>>v;
        p[i-1] = mk(i,v);
    }
    int len = 0;
    while(m--)     
    {
        cin>>e[len].v>>e[len].u;
        cin>>e[len++].w;
    }
    sort(p,p+n,cmp);
    for(int i=1;i

 

你可能感兴趣的:(Codeforces Round #529 (Div. 3)(全部题解))