CodeTON Round 2 (Div. 1 + Div. 2, Rated, Prizes!)

Dashboard - CodeTON Round 2 (Div. 1 + Div. 2, Rated, Prizes!) - CodeforcesCodeforces. Programming competitions and contests, programming communityhttps://codeforces.com/contest/1704

被读题卡住的一场,有空把眼睛捐了

A. Two 0-1 Sequences

给的两个操作其实就是把这个数组的头不断进行替换,后面是动不了的,因此如果a和b要成功配对,倒着看必须有m-1个字符都匹配上,然后看看a前面有没有b的第一个字符头。

#include<bits/stdc++.h>
using namespace std;
#define endl '\n'
#define ll long long
const int maxn = 2e6+10;
const int mod = 1e9+7;

int main(){
    ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
    int t;
    cin>>t;
    while(t--){
        int n,m;
        cin>>n>>m;
        string s1,s2;
        cin>>s1>>s2;
        int j = 1;
        int tar = s2.size()-1;
        for(int i = s1.size()-1;i>=0&&tar>=0;i--){
            if(s1[i]==s2[tar]){
                tar--;
            }
            else{
                if(tar>=1){
                    j = 0;
                    break;
                }
                else{
                    for(int jj = i;jj>=0;jj--){
                        if(s2[0]==s1[jj]){
                            break;
                        }
                        if(jj==0)
                            j = 0;
                    }
                }
            }
        }
        if(!j){
            cout<<"No"<<endl;
        }
        else{
            cout<<"Yes"<<endl;
        }
    }
}

B. Luke is a Foodie

每个蛋糕都要吃,根据题目给的公式转换一下可以得到ai-x<=v<=x+ai,换言之对每个蛋糕都有一个v的区间,我们贪心一下,求出每个蛋糕的区间然后遍历,对应的v的范围是一个重合区间。v的选值就在这个区间范围内,若重合区间矛盾,即不可能重合的时候,就要调整v。

#include<bits/stdc++.h>
using namespace std;
#define endl '\n'
#define ll long long
const int maxn = 2e6+10;
const int mod = 1e9+7;
ll num[maxn];
pair<ll,ll>p[maxn];

int main(){
    ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
    int t;
    cin>>t;
    while(t--) {
        ll n,x;
        cin>>n>>x;
        for(int i = 1;i<=n;i++){
            cin>>num[i];
        }
        for(int i = 1;i<=n;i++){
            p[i].first = num[i]-x;
            p[i].second = num[i]+x;
        }
        pair<ll,ll> r = p[1];
        ll ans = 0;
        for(int i =2;i<=n;i++){
            if(r.first>p[i].second||r.second<p[i].first){
                ans++;
                r = p[i];
                continue;
            }
            if(p[i].first>r.first)
                r.first = p[i].first;
            if(p[i].second<r.second)
                r.second = p[i].second;
        }
        cout<<ans<<endl;
    }
}

C. Virus

差分求出每个幸存城镇的区间,然后模拟一下求出最后存活的城镇总数,然后减去就是感染的城镇数目。很显然,我们要优先保护幸存者城镇更多的区间部分,因为幸存人数少的部分只会减到0,后续不会产生更多负收益,但是如果一直放着更多幸存者城镇的区间部分不管,只会有更多的负收益。sort一下然后反向遍历即可。每个区间部分的最终幸存者城镇个数为

cha[i]-4*(m-i+1)+3,m-i+1是指第几个保护的区间。

有个需要额外注意的地方是当算出的最终幸存者城镇个数为0时,实际幸存者城镇个数为1,因为例如出现1 3这样的情况,实际上直接保护2就可以保下了,即幸存一个城镇,带入公式是幸存0个城镇

#include<bits/stdc++.h>
using namespace std;
#define endl '\n'
#define ll long long
const int maxn = 2e6+10;
const int mod = 1e9+7;
ll num[maxn];
ll cha[maxn];

int main(){
    ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
    int t;
    cin>>t;
    while(t--) {
        ll n,m;
        cin>>n>>m;
        for(int i = 1;i<=m;i++){
            cin>>num[i];
        }
        sort(num+1,num+m+1);
        for(int i = 2;i<=m;i++){
            cha[i] = num[i]-num[i-1]-1;
        }
        cha[1] = num[1]+n-num[m]-1;
        sort(cha+1,cha+m+1);
        ll ans = n;
        for(int i = m;i>=1;i--){
            ll now = cha[i]-4*(m-i+1)+3;
            if(now==0)
                ans-=1;
            else if(now>0)
                ans-=now;
        }
        cout<<ans<<endl;
    }
}

D. Magical Array

构造性解法,从两个操作可以看出来,唯一的差距在于操作1是num[j+1]+1, 操作2是num[j+2]+1,而且两个操作每个数组都操作了不止一次。

此时构造一个sum += num[i]*i即可,这样就能把下标的不同带入值的影响中去,对操作1而言,不会影响sum的值,因为对操作1而言

num[i-1]+1对sum的影响是+i-1,num[i]-1对sum的影响是-i,num[j]-1的影响是-j,num[j+1]+1的影响是j-1,影响总和是i-1-i-j+j-1=0,即操作1不会影响sum的值

对应的操作2的影响总和是i-1-i-j+j-2=1即操作2会让sum++

找到最大的sum然后减去其他sum就是操作2的值了

好牛的思路,也不知道t神是什么脑子,想偷

#include<bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define ll unsigned long long

const int maxn = 2e6;
ll num[maxn];

int main() {
    ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
    int t;
    cin>>t;
    while(t--){
        int n,m;
        ll x;
        cin>>n>>m;
        for(int i = 1;i<=n;i++){
            ll sum = 0;
            for(int j = 1;j<=m;j++){
                cin>>x;
                sum+=j*x;
            }
            num[i] = sum;
        }
        int pos = max_element(num+1,num+1+n)-num;
        if(pos==1){
            cout<<pos<<" "<<num[pos]-num[pos+1]<<endl;
        }
        else{
            cout<<pos<<" "<<num[pos]-num[pos-1]<<endl;
        }
    }
}

  • 4
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值