Codeforces Round #807 (Div.2) A-C
A. Mark the Photographer
题意: 有
2n
个人,其中第i
个人的身高为hi
要求: 将这
2n
个人排成两排,要求前面的人比后面的人至少高k
。若可以则输出YES
,否则输出NO
。
注意: 我们注意到第三组样例中,
k=2
时,只有两个人分别高6
和8
的这种情况也满足要求。
思路: 首先排序,排序后只需:分别判断 从第
i
到第n
个人的身高是否 分别 和第n+1
到第n+n
个人的身高差是否大于k
。也就是判断第j
个人和第j+n
个人的身高差值是否大于k
。
注意:排序后,若1
到n
之间有可以与1
配对的。他们之间的差值绝对没有1
与n+1
的差值大,因为排序后严格非降序,第n+1
个严格大于等于之前的数字。
代码:
#include<bits/stdc++.h>
#define IOS std::ios::sync_with_stdio(false);cin.tie(NULL);cout.tie(NULL);
#define ll long long
#define int long long
#define endl "\n"
using namespace std;
const int mn = 1e5+10;
const int mod = 1e9+7;
const int N = 2e5+10;
int dr[4][2]={{-1,0},{1,0},{0,-1},{0,1}};
int a[mn];
void solve(){
int n,k;
cin >>n>>k;;
for(int i=1;i<=n*2;i++){
cin >>a[i];
}
sort(a+1,a+1+n*2);
for(int i=1;i<=n;i++){
if(a[i]+k>a[n+i]){
cout <<"NO"<<endl;
return;
}
}
cout <<"YES"<<endl;
}
signed main(){
IOS;
int T=1;
cin >>T;
while(T--){
solve();
}
return 0;
}
B. Mark the Dust Sweeper
题意: 现有
n
个房间,第i
个房间有非负个垃圾ai
,每一次操作他可以进行如下步骤:
- 选择
i
和j
,i<j
。同时要求ai
,a(i+1)
,…
,a(j-1)
全部严格大于0
;- 将第
i
个房间的垃圾ai
变成ai-1
;- 将第
j
个房间的垃圾aj
变成aj-1
。
要求: 要将所有的垃圾放到最后一个房间,使得
a1
,a2
,…
,a(n-1)
均为0
;
思路:简单来讲,上述操作就是
i
到j-1
房间内均有垃圾,然后将第i
个房间的一个垃圾转移到第j
个房间内。**因此:**从第一个有垃圾的房间到第n-1
个房间全部有垃圾,我们就可以使得j
选择为n
,从而可以将所有垃圾移到n
房间内;所以只需从第一个有垃圾的房间到n-1
个房间,遇见0
就将答案+1(相当于搭桥),遇见非0
就将答案+这个数字。
代码:
#include<bits/stdc++.h>
#define IOS std::ios::sync_with_stdio(false);cin.tie(NULL);cout.tie(NULL);
#define ll long long
#define int long long
#define endl "\n"
using namespace std;
const int mn = 1e5+10;
const int mod = 1e9+7;
const int N = 2e5+10;
int dr[4][2]={{-1,0},{1,0},{0,-1},{0,1}};
int a[N];
void solve(){
int n;
cin >>n;
for(int i=1;i<=n;i++){
cin >>a[i];
}
bool pd = false;
int ans = 0;
for(int i=1;i<n;i++){
if(!pd&&a[i]!=0){
pd=true;
}
if(pd){
if(a[i]==0) ans++;
else ans+=a[i];
}
}
cout <<ans<<endl;
}
signed main(){
IOS;
int T=1;
cin >>T;
while(T--){
solve();
}
return 0;
}
C. Mark and His Unfinished Essay
题意: 首先给三个数字
n
,c
,q
分别代表字符串的长度n
,c
次拼接操作和q
次询问。给定长度为
n
的字符串。接下来
c
行,每行给定两个数字l
和r
,代表将字符串l
至r
的字符拼接在字符串后方。接下来
q
行,每行给定一个数字k
,代表询问第k
个字符。
注意: 首先看数据范围
l
,r
和k
的范围均为1至10^18
,所以不能暴力,否则会导致时间和空间超时。
思路: 首先判断
k
是否大于n
,若大于的话则必定是输出拼接的字符,则将k
减去n
,说明要在第一次拼接操作里面找一个字符,若k-n
的长度还大于第一个r-l+1(就是第一次拼接的长度)
,则将k-n
再减去r-l+1
,再去第二次拼接操作里面查找……直到找到一个字符……若找到的字符下标还大于n
,则重复上述操作,从第一次拼接操作中查找,若不满足再从第二次……
代码:
#include<bits/stdc++.h>
#define IOS std::ios::sync_with_stdio(false);cin.tie(NULL);cout.tie(NULL);
#define ll long long
#define int long long
#define endl "\n"
using namespace std;
const int mn = 1e5+10;
const int mod = 1e9+7;
const int N = 2e5+10;
int dr[4][2]={{-1,0},{1,0},{0,-1},{0,1}};
struct node{
int l,r;
}a[40];
void solve(){
int n,c,q;
cin >>n>>c>>q;
string s;
cin >>s;
for(int i=1;i<=c;i++){
cin >>a[i].l>>a[i].r;
}
while(q--){
int x;
cin >>x;
while(x>s.length()){
int i=1;
x-=s.length();
while( x-(a[i].r-a[i].l+1) > 0 ){
x-=(a[i].r-a[i].l+1);
i++;
}
x+=(a[i].l-1);
}
cout <<s[x-1]<<endl;
}
}
signed main(){
IOS;
int T=1;
cin >>T;
while(T--){
solve();
}
return 0;
}
代码解读:
4 3 1
mark
1 4
5 7
3 8
10
我们要找第10
个字符,则说明从第一次操作中找第6(10-4)
个字符,也就是从第二个里面找第2
个字符,也就是字符串中的第6(第二次操作中5是第一个,则6是第二个)
个字符。
6>4
则重复从第一次操作查找:找第6
个字符,就说明从第一次操作中找第2
个字符,也就是字符串中的第2(第一次操作中1是第一个,则2是第二个)
个字符。就是mark
中的a
。