A. Mark the Photographer
分析
2n个数分成两行,第二行的数至少要比第一行多x。给出的数,是否可以这样排列。
将给出2n个数进行排序,从小往大遍历找比它大x的数,找到后这个数之后再找的时候就跳过,直到找够n组这样的数,就是可以排列的。
把最小的n个数放在第一排就可以,因为前面的数都有大x的数的话,后面的数肯定会大,然后就可以随便换位置。
代码
#include<bits/stdc++.h>
#define pb push_back
#define ll long long
#define guanliu ios::sync_with_stdio(0),cin.tie(0),cout.tie(0)
using namespace std;
const ll maxn=2e5+10;
const ll mod=1e9+7;
const ll INF=0x3f3f3f3f;
const double pi=acos(-1);
struct node{
int h;
int f;
}h[205];
bool cmp(node a,node b)
{
return a.h<b.h;
}
int main()
{
guanliu;
int t;
cin>>t;
while(t--)
{
int n,x;
cin>>n>>x;
int f=1;
for(int i=1;i<=2*n;i++)
{
cin>>h[i].h;
h[i].f=0;
}
sort(h+1,h+1+2*n,cmp);
for(int i=1;i<=n;i++)
{
int ff=0,j;
for(j=i;j<=2*n;j++)
{
if(h[j].f==1) continue;
if(h[i].h+x<=h[j].h)
{
h[j].f=1;
ff=1;
break;
}
}
if(j==2*n+1&&ff==0)
{
f=0;
break;
}
}
if(f==1) cout<<"YES"<<endl;
else cout<<"NO"<<endl;
}
return 0;
}
B. Mark the Dust Sweeper
分析
n个数,选择i,j号两个数,使得i-1,j+1,并且操作之后,所得的数之间的数都要大于0,用最小的操作数,将前n-1个数都减小为0。因为之间的数都要大于0,所以先将从第一个不为0的数到第n-1个数之间的0填满,再将数都与最后一个数进行操作,最小操作数就是0的个数加上前n-1个不为0的数值。
注意:答案很大需要开ll
代码
#include<bits/stdc++.h>
#define pb push_back
#define ll long long
#define guanliu ios::sync_with_stdio(0),cin.tie(0),cout.tie(0)
using namespace std;
const ll maxn=2e5+10;
const ll mod=1e9+7;
const ll INF=0x3f3f3f3f;
const double pi=acos(-1);
int a[maxn];
int main()
{
guanliu;
int t;
cin>>t;
while(t--)
{
int n;
int f=0;
cin>>n;
ll ans=0;
for(int i=1;i<=n;i++)
{
cin>>a[i];
}
for(int i=1;i<n;i++)
{
if(a[i]!=0) f=1;
if(a[i]==0&&f==1) ans++;
ans+=a[i];
}
if(f==0) ans=0;
cout<<ans<<endl;
}
return 0;
}
C. Mark and His Unfinished Essay
分析
给一个原始字符串,对原始字符串进行c次操作,每次都将字符串的l到r复制到最后变成一个新字符串。q次查询,最后的字符串k的位置是什么字母。由于最后字符串的长度最长达到1e18,所以不可能将字符串模拟出来,不能模拟字符串,就模拟每次操作之后,字符串的长度,对应的l,r区间,最后回溯到原始字符串找到原来的位置。
注意:所有都要开ll!!
代码
#include<bits/stdc++.h>
#define pb push_back
#define ll long long
#define guanliu ios::sync_with_stdio(0),cin.tie(0),cout.tie(0)
using namespace std;
const ll maxn=2e5+10;
const ll mod=1e9+7;
const ll INF=0x3f3f3f3f;
const double pi=acos(-1);
ll l[50],r[50];
ll lb[50],rr[50];
int main()
{
guanliu;
int t;
cin>>t;
while(t--)
{
ll n,c,q;
cin>>n>>c>>q;
string s;
cin>>s;
ll len=s.size();
for(ll i=1;i<= c;i++)
{
cin>>l[i]>>r[i];
ll now=r[i]-l[i]+1;
lb[i]=len+1;
rr[i]=lb[i]+now-1;
len+=now;
}
while(q--)
{
ll k;
cin>>k;
for(ll i=c;i>=1;i--)
{
if(lb[i]<=k&&k<=rr[i])
{
k-=lb[i]-l[i];
}
}
cout<<s[k-1]<<endl;
}
}
return 0;
}
D. Mark and Lightbulbs
分析
两个01串s和t,对s取一个i并且,对
的值进行反转,使s等于t,求最小操作次数。
分析题意,发现每次操作都是对三个字符组成的字符串进行操作。也就是001,011,100,110,这四个字符串。下一步发现,中间的i转换前后,总会与它左右两边的一个相同,于是得出式子,、
或者
,将式子换成01就是01或者10,而这一步转换就是进行异或。原始的问题就转换为将s和t相邻位置异或结果组成的01串进行01->10、10->01操作。而这种操作的最小操作数就是将a中的1移到b中1的位置的最小操作数。
没有解的情况就是:首尾本身就不同,也无法通过操作使其相同;转换后a,b中1的个数不同,无法满足将a中的1移到b的位置。
代码
#include<bits/stdc++.h>
#define pb push_back
#define ll long long
#define guanliu ios::sync_with_stdio(0),cin.tie(0),cout.tie(0)
using namespace std;
const ll maxn=2e5+10;
const ll mod=1e9+7;
const ll INF=0x3f3f3f3f;
const double pi=acos(-1);
int a[maxn],b[maxn];
int main()
{
guanliu;
int q;
cin>>q;
while(q--)
{
int n,f=1;
string s,t;
ll ans=0;
cin>>n;
cin>>s>>t;
if(s[0]!=t[0]||s[n-1]!=t[n-1]) f=0;
int cnta=0,cntb=0;
for(int i=1;i<n;i++)
{
a[i]=s[i]^s[i-1];
b[i]=t[i]^t[i-1];
if(a[i]==1) cnta++;
if(b[i]==1) cntb++;
}
if(cnta!=cntb) f=0;
int r=1;
for(int i=1;i<n;i++)
{
if(a[i])
{
while(r<=n-2&&b[r]==0) r++;
ans+=abs(i-r);
r++;
}
}
if(f==0) cout<<"-1"<<endl;
else cout<<ans<<endl;
}
return 0;
}