Codeforces Round #767 (Div. 2) ABCD题解

A. Download More RAM

思路
签 到 题 签到题
按 照 a 从 小 到 大 排 序 按照a从小到大排序 a
只 要 k > = a , 就 + = 对 应 的 b 只要k>=a,就+=对应的b k>=a+=b
输 出 k 即 可 输出k即可 k
时间复杂度 O n l o g n Onlogn Onlogn

#include <bits/stdc++.h>
#define fer(i,a,b) for(re i = a ; i <= b ; ++ i)
#define der(i,a,b) for(re i = a ; i >= b ; -- i)
#define cf int _; cin>> _; while(_--)
#define all(x) (x).begin(),(x).end()
#define sz(x) ((int)(x).size())
#define sf(x) scanf("%lld",&x)
#define pll pair<int,int> 
#define re register int
#define lb lower_bound
#define up upper_bound
#define int long long 
#define pb push_back
#define y second 
#define x first 
using namespace std;
inline void sf2(int &a , int &b) { sf(a) , sf(b) ;}
inline void sf3(int n , int a[]) {fer(i,1,n) sf(a[i]);} ;
inline void de(auto x) {cout << x << "\n" ;}
inline void de2(auto a , auto b) {cout << a << " " << b << "\n" ;}
inline void de3(int n , auto a[]){fer(i,1,n) cout << a[i] << " " ;puts("");}
inline void mo(int &a , int b) {a = (a % b + b) % b ;}
inline int gcd(int a,int b){return b ? gcd(b , a % b) : a ;}
inline int qpow(int a,int b,int c){int res=1%c;a%=c;while(b>0){if(b&1)res=res*a%c;a=a*a%c;b>>=1;}return res;}
inline int qadd(int a,int b,int c){int res=0;a%=c;while(b>0){if(b&1)res=(res+a)%c;a=(a+a)%c;b>>=1;}return res;} 
const int inf = 0x3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f ;
const int N = 1e6 + 10 , M = 3010 , mod = 1e9 + 7 ;
const double eps = 1e-7 , pi = acos(-1.0) ;
 
int n , k ;
struct ai{
    int a , b ;
}q[N] ;
bool cmp(ai x , ai y)
{
    return x.a < y.a ;
}
 
signed main()
{
    cf
    {
        cin >> n >> k ;
        fer(i,1,n) sf(q[i].a) ;
        fer(i,1,n) sf(q[i].b) ;
        
        sort(q + 1 , q + 1 + n , cmp) ;
        
        fer(i,1,n)
        {
            if(k >= q[i].a)
                k += q[i].b ;
        }
        
        de(k) ;
    }
    return 0;
}

B. GCD Arrays

思路
读 完 题 目 第 一 个 想 到 的 就 是 g c d ( x , x + 1 ) = 1 读完题目第一个想到的就是gcd(x,x+1)=1 gcd(x,x+1)=1
显 然 这 个 性 质 不 是 特 别 关 键 显然这个性质不是特别关键

在 仔 细 想 想 , 只 要 可 能 的 g c d > 1 即 可 在仔细想想,只要可能的gcd>1即可 gcd>1
2 又 是 除 1 之 外 , [ l , r ] 中 因 数 最 多 的 一 个 数 2又是除1之外,[l,r]中因数最多的一个数 21[l,r]
所 以 g c d > 1 , 具 体 是 多 少 , 操 作 数 最 小 的 一 定 是 2 所以gcd>1,具体是多少,操作数最小的一定是2 gcd>12

那 么 统 计 一 下 [ l , r ] 中 有 多 少 个 奇 数 那么统计一下[l,r]中有多少个奇数 [l,r]
奇 数 是 一 定 要 和 另 外 一 个 偶 数 乘 起 来 奇数是一定要和另外一个偶数乘起来
所 以 如 果 奇 数 小 于 等 于 k , 输 出 Y E S 所以如果奇数小于等于k,输出YES kYES

在 特 殊 判 断 一 下 a = b , 并 且 a ! = 1 的 情 况 在特殊判断一下a=b,并且a!=1的情况 a=ba!=1
因 为 g c d ( a , a ) = a [ a ! = 1 ] 因为gcd(a,a) = a [ a != 1] gcd(a,a)=a[a!=1]
这 种 情 况 也 是 Y E S 这种情况也是YES YES
时间复杂度 O t Ot Ot

#include <bits/stdc++.h>
#define fer(i,a,b) for(re i = a ; i <= b ; ++ i)
#define der(i,a,b) for(re i = a ; i >= b ; -- i)
#define cf int _; cin>> _; while(_--)
#define all(x) (x).begin(),(x).end()
#define sz(x) ((int)(x).size())
#define sf(x) scanf("%lld",&x)
#define pll pair<int,int> 
#define re register int
#define lb lower_bound
#define up upper_bound
#define int long long 
#define pb push_back
#define y second 
#define x first 
using namespace std;
inline void sf2(int &a , int &b) { sf(a) , sf(b) ;}
inline void sf3(int n , int a[]) {fer(i,1,n) sf(a[i]);} ;
inline void de(auto x) {cout << x << "\n" ;}
inline void de2(auto a , auto b) {cout << a << " " << b << "\n" ;}
inline void de3(int n , auto a[]){fer(i,1,n) cout << a[i] << " " ;puts("");}
inline void mo(int &a , int b) {a = (a % b + b) % b ;}
inline int gcd(int a,int b){return b ? gcd(b , a % b) : a ;}
inline int qpow(int a,int b,int c){int res=1%c;a%=c;while(b>0){if(b&1)res=res*a%c;a=a*a%c;b>>=1;}return res;}
inline int qadd(int a,int b,int c){int res=0;a%=c;while(b>0){if(b&1)res=(res+a)%c;a=(a+a)%c;b>>=1;}return res;} 
const int inf = 0x3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f ;
const int N = 1e6 + 10 , M = 3010 , mod = 1e9 + 7 ;
const double eps = 1e-7 , pi = acos(-1.0) ;
 
int get(int x) // 返回1-x中有多少个奇数
{
    return (x + 1) / 2 ;
}
 
signed main()
{
    cf
    {
        int a , b , k ;
        sf2(a , b) , sf(k) ;
        
        int s = get(b) - get(a - 1) ;
        if(s <= k || (a == b && a != 1)) puts("YES") ;
        else puts("NO") ;
        
    }
    return 0;
}

C. Meximum Array

思路
首 先 要 让 字 典 序 最 大 首先要让字典序最大
那 么 肯 定 优 先 选 最 大 的 那么肯定优先选最大的

我 们 可 以 发 现 答 案 的 第 一 个 数 是 整 个 序 列 里 面 的 M E X 我们可以发现答案的第一个数是整个序列里面的MEX MEX
那 么 我 们 首 先 消 除 的 前 k 个 数 那么我们首先消除的前k个数 k

要 保 证 这 k 个 数 的 M E X = 整 个 序 列 的 M E X 要保证这k个数的MEX=整个序列的MEX kMEX=MEX
并 且 保 证 k 最 小 , 这 样 你 可 以 选 更 多 的 数 并且保证k最小,这样你可以选更多的数 k

删 掉 之 后 的 下 一 个 数 是 剩 下 一 整 个 序 列 的 M E X 删掉之后的下一个数是剩下一整个序列的MEX MEX
模 拟 上 述 过 程 即 可 模拟上述过程即可

具 体 可 以 看 代 码 细 节 具体可以看代码细节
时间复杂度 O n On On

#include <bits/stdc++.h>
#define fer(i,a,b) for(re i = a ; i <= b ; ++ i)
#define der(i,a,b) for(re i = a ; i >= b ; -- i)
#define cf int _; cin>> _; while(_--)
#define all(x) (x).begin(),(x).end()
#define sz(x) ((int)(x).size())
#define sf(x) scanf("%lld",&x)
#define pll pair<int,int> 
#define re register int
#define lb lower_bound
#define up upper_bound
#define int long long 
#define pb push_back
#define y second 
#define x first 
using namespace std;
inline void sf2(int &a , int &b) { sf(a) , sf(b) ;}
inline void sf3(int n , int a[]) {fer(i,1,n) sf(a[i]);} ;
inline void de(auto x) {cout << x << "\n" ;}
inline void de2(auto a , auto b) {cout << a << " " << b << "\n" ;}
inline void de3(int n , auto a[]){fer(i,1,n) cout << a[i] << " " ;puts("");}
inline void mo(int &a , int b) {a = (a % b + b) % b ;}
inline int gcd(int a,int b){return b ? gcd(b , a % b) : a ;}
inline int qpow(int a,int b,int c){int res=1%c;a%=c;while(b>0){if(b&1)res=res*a%c;a=a*a%c;b>>=1;}return res;}
inline int qadd(int a,int b,int c){int res=0;a%=c;while(b>0){if(b&1)res=(res+a)%c;a=(a+a)%c;b>>=1;}return res;} 
const int inf = 0x3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f ;
const int N = 1e6 + 10 , M = 3010 , mod = 1e9 + 7 ;
const double eps = 1e-7 , pi = acos(-1.0) ;
 
int n ;
int a[N] ;
int st[N] ;
int s[N] ;
 
signed main()
{
    cf
    {
        cin >> n ;
        fer(i,0,n) st[i] = 0 ;
        fer(i,1,n) sf(a[i]) , st[a[i]] ++ ;
        int k = 0 ;
        while(st[k]) k ++ ;
        // k为整个序列的MEX
        vector<int> v ;
        // v数组记录答案
        
        int t = 0 ; 
        // t表示从0到k-1出现了多少个数
        fer(i,0,k) s[i] = 0 ;
        for(int i = 1 ; i <= n ; i ++)
        {
            if(a[i] <= k - 1)
            {
                if(!s[a[i]])
                {
                    s[a[i]] ++ ;
                    t ++ ;
                }
                else s[a[i]] ++ ;
            }
            
            if(t == k) // 如果连续出现的数的个数=k了
            {
                v.pb(k) ;
                fer(i,0,k - 1) st[i] -= s[i] ;
                // 在st数组里面减掉这些数的出现次数
                t = 0 ; 
                k = 0 ;
                while(st[k]) k ++ ;
                // 重新找到整个序列的MEX
                fer(i,0,k) s[i] = 0 ;
            }
        }
        
        // 输出答案
        de(sz(v)) ;
        for(auto i : v) cout << i << " " ;
        puts("") ;
        
    }
    return 0;
}

D. Peculiar Movie Preferences

思路
如 果 出 现 了 同 一 个 字 母 组 成 的 字 符 串 一 定 为 Y E S 如果出现了同一个字母组成的字符串一定为YES YES

在 考 虑 长 度 为 2 的 字 符 串 在考虑长度为2的字符串 2
x y 和 y x 同 时 出 现 说 明 可 以 xy和yx同时出现说明可以 xyyx

在 考 虑 长 度 为 3 的 字 符 串 在考虑长度为3的字符串 3
x y z 和 z y x 同 时 出 现 说 明 可 以 xyz和zyx同时出现说明可以 xyzzyx

在 考 虑 长 度 为 2 和 3 的 拼 接 在考虑长度为2和3的拼接 23
如 果 出 现 了 x y z y x [ x y z + y x ] 如果出现了xyzyx[xyz+yx] xyzyx[xyz+yx]
x y z 在 前 面 y x 在 后 面 xyz在前面yx在后面 xyzyx

或 者 是 x y z y x [ x y + z y x ] 或者是xyzyx[xy+zyx] xyzyx[xy+zyx]
x y 在 前 面 , z y x 在 后 面 xy在前面,zyx在后面 xy,zyx
这 2 种 情 况 都 可 以 这2种情况都可以 2
其 他 情 况 均 为 不 可 能 其他情况均为不可能

为 什 么 不 讨 论 2 个 长 度 为 3 和 3 个 长 度 为 2 的 拼 接 为什么不讨论2个长度为3和3个长度为2的拼接 2332
因 为 如 果 出 现 了 这 样 的 情 况 , 说 明 一 定 出 现 了 长 度 为 2 和 3 的 拼 接 因为如果出现了这样的情况,说明一定出现了长度为2和3的拼接 23
时间复杂度 O n l o g n Onlogn Onlogn

#include <bits/stdc++.h>
#define fer(i,a,b) for(re i = a ; i <= b ; ++ i)
#define der(i,a,b) for(re i = a ; i >= b ; -- i)
#define cf int _; cin>> _; while(_--)
#define all(x) (x).begin(),(x).end()
#define sz(x) ((int)(x).size())
#define sf(x) scanf("%lld",&x)
#define pll pair<int,int> 
#define re register int
#define lb lower_bound
#define up upper_bound
#define int long long 
#define pb push_back
#define y second 
#define x first 
using namespace std;
inline void sf2(int &a , int &b) { sf(a) , sf(b) ;}
inline void sf3(int n , int a[]) {fer(i,1,n) sf(a[i]);} ;
inline void de(auto x) {cout << x << "\n" ;}
inline void de2(auto a , auto b) {cout << a << " " << b << "\n" ;}
inline void de3(int n , auto a[]){fer(i,1,n) cout << a[i] << " " ;puts("");}
inline void mo(int &a , int b) {a = (a % b + b) % b ;}
inline int gcd(int a,int b){return b ? gcd(b , a % b) : a ;}
inline int qpow(int a,int b,int c){int res=1%c;a%=c;while(b>0){if(b&1)res=res*a%c;a=a*a%c;b>>=1;}return res;}
inline int qadd(int a,int b,int c){int res=0;a%=c;while(b>0){if(b&1)res=(res+a)%c;a=(a+a)%c;b>>=1;}return res;} 
const int inf = 0x3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f ;
const int N = 1e6 + 10 , M = 3010 , mod = 1e9 + 7 ;
const double eps = 1e-7 , pi = acos(-1.0) ;
 
int n ;
string q[N] ;
 
signed main()
{
    cf
    {
        cin >> n ;
        int f1 = 0 ;
        map<string,int> mp , p;
        fer(i,1,n) 
        {
            cin >> q[i] , mp[q[i]] ++ ;    
            if(sz(q[i]) == 1) f1 = 1 ;
            else if(sz(q[i]) == 2) 
            {
                if(q[i][0] == q[i][1]) 
                    f1 = 1 ;
            }
            else 
            {
                if(q[i][0] == q[i][1] && q[i][0] == q[i][2])
                    f1 = 1 ;
            }
            // 如果出现了同一个字母组成的字符串一定为YES
        }
        
        fer(i,1,n)
        {
            p[q[i]] ++ ;
            if(sz(q[i]) == 2)
            {
                string t = q[i] ;
                reverse(all(t)) ;
                if(mp[t]) f1 = 1 ;
                // xy和yx同时出现说明可以
            }
            else if(sz(q[i]) == 3)
            {
                string t1 = "" ;
                string t2 = "" ;
                
                string t = q[i] ;
                reverse(all(t)) ;
                if(mp[t]) f1 = 1 ;
                // xyz和zyx时出现说明可以
                
                fer(j,1,2) t1 = t1 + q[i][j] ;
                fer(j,0,1) t2 = t2 + q[i][j] ;
                
                reverse(all(t1)) ;
                reverse(all(t2)) ;
                if(p[t1] || mp[t2]) f1 = 1 ;
                // 如果出现了xyzyx[xyz+yx]
                // 或者是xyzyx[xy+zyx] 也说明可以
            }
            mp[q[i]] -- ;
        }
        
        if(f1) puts("YES") ;
        else puts("NO") ;
    }
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值