codeforces 706 div2题解

A Split it!

思路
翻转后看前k个连续是否相等,并且满足 k ∗ 2 + 1 < = n k*2+1 <= n k2+1<=n

代码

#include<bits/stdc++.h>
#include<iostream>
#include <stdio.h>
using namespace std;
const int maxn=200005;
const int base=131;
typedef long long ll;
#define pi acos(-1)
#define INF 0x3f3f3f3f
#define mod 998244353
const int inf=1<<30;
int a[maxn];
int b[maxn];
vector<int> pos;
int main()
{
    
    
    //freopen("data.in","r",stdin);
    //freopen("1.out","w",stdout);
    int t,n,k;
    cin>>t;
    string s,s1;
    while(t--){
    
    
        cin>>n>>k;
        cin>>s;
        s1 = s;
        reverse(s.begin(),s.end());
        //cout<<s<<endl;
        int f = 0,cnt = 0;
        for(int i = 0;i < n ; i++ ){
    
    
            if(s[i] != s1[i] ){
    
    
                if(cnt >= k)
                    f = 1;
                break;
            }
            cnt++;
            if(cnt >= k){
    
    
                f = 1;
                break;
            }
        }
        if(k == 0 || ( f && (k*2+1 <= n)))
            cout<<"YES"<<endl;
        else
            cout<<"NO"<<endl;

    }
    return 0;
}

B Max and Mex

思路在这里插入图片描述可以用 a + b + 1 2 \frac{a+b+1}{2} 2a+b+1计算
如果加入的这个b已经存在于序列中,mex和max不会变,答案为原序列中不同元素个数。

如果b不存在于序列中,并且原序列不是连续的,则有 m e x < m a x mex < max mex<max,那么b最小为 m e x + m e x + 1 + 1 2 \frac{mex +mex+1+1}{2} 2mex+mex+1+1,即 m e x + 1 mex+1 mex+1,加入后b后 m e x ′ mex' mex m a x ′ max' max不变,答案为原序列中不同元素个数加一。

如果b不存在于序列中,并且原序列是连续的则有 m e x > m a x mex > max mex>max,,mex一定为 m a x + 1 max+1 max+1,那么b为 m a x + m a x + 1 + 1 2 \frac{max +max+1+1}{2} 2max+max+1+1,即 m a x + 1 max+1 max+1
加入后b后, m e x ′ mex' mex变为 m e x + 1 = m a x + 2 mex+1= max +2 mex+1=max+2 m a x ′ max' max变为 m a x + 1 max+1 max+1,新的 b ′ = b + 1 = m a x + 2 b'=b+1=max+2 b=b+1=max+2,以此类推……答案为原序列中不同元素个数加k。

代码

#include<bits/stdc++.h>
#include<iostream>
#include <stdio.h>
using namespace std;
const int maxn=200005;
const int base=131;
typedef long long ll;
#define pi acos(-1)
#define INF 0x3f3f3f3f
#define mod 998244353
const int inf=1<<30;
ll a[maxn];
set<ll> vis;
int main()
{
    
    
    //freopen("data.in","r",stdin);
    //freopen("1.out","w",stdout);
    ll t,n,k;
    cin>>t;
    string s,s1;
    while(t--){
    
    
        cin>>n>>k;
        vis.clear();
        memset(a,0,sizeof(a));
        for(ll i = 1;i <= n;i++){
    
    
            cin>>a[i];
            vis.insert(a[i]);
        }
        sort(a+1,a+1+n);
        ll aa,bb;
        bb = a[n];
        ll cnt = 0;
        if(k == 0){
    
    
            cout<<vis.size()<<endl; 
            continue;
        }
        ll i ;
        for( i =1 ;i <= n;i++){
    
    
            if(i == 1 && a[i] != 0)
            {
    
    
                 aa = 0;
                 break;
            }
            if(a[i+1] != a[i]+1 ){
    
    
                aa = a[i]+1;
                break;
            }
        }
        ll b = (aa + bb +1) / 2;
        cnt++;
        if(vis.find(b) != vis.end() || cnt == k){
    
    
            vis.insert(b);
            cout<<vis.size()<<endl; 
        }
        else{
    
     //找不到
            if(aa > bb)
                cout<<vis.size() + k<<endl;
            else
                cout<<vis.size() + 1<<endl;
        }
    }
    return 0;
}

C Diamond Miner

思路
将所有的x和y都映射到第一象限上,依次将最小的x点和y点一一对应求距离即可。

代码

#include<bits/stdc++.h>
#include<iostream>
#include <stdio.h>
using namespace std;
const int maxn=200005;
const int base=131;
typedef long long ll;
#define pi acos(-1)
#define INF 0x3f3f3f3f
#define mod 998244353
const int inf=1<<30;
ll a[maxn],b[maxn];
int main()
{
    
    
    //freopen("data.in","r",stdin);
    //freopen("1.out","w",stdout);
    ll t,n,k;
    cin>>t;
    while(t--){
    
    
        cin>>n;
        ll x ,y;
        int cnt1 = 0,cnt2 = 0; 
        for(int i = 1;i <= n *2;i++){
    
    
            cin>>x>>y;
            if(x == 0){
    
    
                if(y > 0)
                a[++cnt1] = y;
                else a[++cnt1] = -y;
            }
            if(y == 0){
    
    
                if(x > 0)
                b[++cnt2] = x;
                else b[++cnt2] = -x;
            }
        }
    sort(b+1,b+n+1);
    sort(a+1,a+n+1);
    double ans = 0.0;
    for(int i =1;i <= n; i++){
    
    
        ans += sqrt(a[i] * a[i]*1.0 + b[i] *b[i]*1.0);
    }
    printf("%.15lf\n",ans);
    }
    return 0;
}

D Let’s Go Hiking

题意:给定一个序列,Qingshan只能沿着单调下降的方向移动,Daniel只能沿着单调上升的方向移动,Q先移动,D后手,谁先不能移动谁输。

思路
首先在这个n长的序列中可能有m个单调的连续子序列。Q和D都只能在单调子序列上移动,Q选择序列中最大的位置,D选择最小的位置。

为了让自己的移动步数多,Q和D都会选择最长的单调序列,因为如果让出最长的序列则必输。如果只有一个最长的单调序列,Q和D相当于往对方移动,必会相遇。由于Q先手,Q必输。

有多条等长的间隔开的单调序列,Q和D能移动的距离相等,因为Q先手,Q必输。

有连接在一起的等长单调序列时,即一个波形,单调上升和单调下降的部分长度相等为L。如果长度L为偶数,和上面的情况相同,Q必输。

如果每部分长度L为奇数,Q先手,Q可以往往两个方向移动。长度为奇数下Q和D相遇,Q先手D必输,所以D只能放在第二小的位置将这种相遇转化为长度为偶数的相遇;但是Q可以选择向另一边移动,Q和D同方向移动,Q还是可以L次,D放在第二小的位置只能移动L-1次,D必输。

代码

#include<bits/stdc++.h>
#include<iostream>
#include <stdio.h>
using namespace std;
const int maxn=200005;
const int base=131;
typedef long long ll;
#define pi acos(-1)
#define INF 0x3f3f3f3f
#define mod 998244353
const int inf=1<<30;
int p[maxn];
int l[maxn],r[maxn];

int main()
{
    
    
    //freopen("data.in","r",stdin);
    //freopen("1.out","w",stdout);
    int n;
    cin>>n;
    for(int i = 1; i <= n;i++){
    
    
        cin>>p[i];
    }
    l[1] = 1;
    r[n] = 1;
    for(int i =2 ;i <= n;i++)
        l[i] = (p[i] > p[i-1])? l[i-1] + 1 : 1;
    for(int i = n-1 ;i >= 1; i--)
        r[i] = (p[i] > p[i+1]) ? r[i+1] + 1 : 1;
    int ma = 0,cnt = 0,vis = 0;
    for(int i = 1;i <= n;i++){
    
    
        if(l[i] > ma || r[i] > ma){
    
    
            ma = max(l[i],r[i]);
            cnt = 1;
            vis = i;
        }
        else if(l[i] == ma || r[i] == ma){
    
    
            cnt = 0;
        }
    }
    int ans;
    int mx = l[vis] > r[vis]? l[vis] : r[vis];
    int mi = l[vis] > r[vis]? r[vis] : l[vis];
    if(cnt && mx % 2 &&mx == mi)
        ans = 1;
    else
        ans = 0;
    cout<<ans<<endl;
    return 0;
}

E Garden of the Sun

题意
n行m列的农田里,种了n*m朵太阳花,因阳光猛烈太阳花死掉了许多,剩下的空格子没有共同边或角。

你需要移除剩下的太阳花,使得满足:一、空格是联通的,二、任何两个空格间都有一条简单路径,即所有的空格是不成环的。

思路
构造,构的我心态炸了,就硬构。

每三行把其中一行全置空,行是三的倍数就置空中间的,不是置空第一行,然后联通剩下两行就可以了。

代码

#include<bits/stdc++.h>
#include<iostream>
#include <stdio.h>
using namespace std;
const int maxn=60005;
const int base=131;
typedef long long ll;
#define pi acos(-1)
#define INF 0x3f3f3f3f
#define mod 998244353
const int inf=1<<30;
string g[maxn];
string ans[maxn];
 
int main()
{
    
    
    //freopen("data.in","r",stdin);
    //freopen("1.out","w",stdout);
    // ios::sync_with_stdio(false); cin.tie(0);
    int t,n,m;
    cin>>t;
    while(t--){
    
    
        cin>>n>>m;
        for(int i = 0; i < n; i++){
    
    
            g[i].clear();
            cin>>g[i];
        }
        for(int i = (n%3) == 0; i < n;){
    
    
            for(int j = 0; j < m; j++)
                g[i][j] = 'X';
            i += 3;
            if(i >= n)
                break;
            int pos = 1;
            if(m == 1 || (g[i - 1][1] != 'X' && g[i - 2][1] != 'X' )){
    
    
                pos = 0;
            }
            g[i - 1][pos] = 'X';
            g[i - 2][pos] = 'X';
        }
        for(int i = 0; i < n; i++)
            cout<<g[i]<<endl;
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/u011612364/article/details/114678047
今日推荐