A
题解:有一个人只能写10^x(x>=2)这样的数字但是他把^这个符号忘了以至于只能写成10x这样的数,现在你要根据这些数字判断是不是原来他能写的数字 依据:1. 10打底 2,x>=2
#include<iostream>
#include<cstring>
using namespace std;
int main()
{
int t;
cin>>t;
while(t--)
{
string grn;
cin>>grn;
bool flag=false;
bool mc=false;
if(grn[0]=='1'&&grn[1]=='0')
flag=true;
int cnt=0;
int temp=0;
for(int i=2;i<grn.size();i++)
{
temp=temp*10+(grn[i]-'0');
}
if(temp>=2&&(grn[2]-'0')>0)
mc=true;
if(flag&&mc)
{
cout<<"YES"<<endl;
}
else
cout<<"NO"<<endl;
}
return 0;
}
B
题意:一辆车上,如果没有人,那么所有座位随便坐。如果有人,那么就只能做他的旁边。
#include<bits/stdc++.h>
using namespace std;
const int N=200010;
int mc[N],grn[N];
int t,n;
int main()
{
cin>>t;
while(t--)
{
cin>>n;
for(int i=0;i<n;i++) cin>>mc[i];
memset(grn,0,sizeof(grn));
bool flag=true;
grn[mc[0]]++;
if(mc[0]+1<=n)
grn[mc[0]+1]++;
if(mc[0]-1>=1)
grn[mc[0]-1]++;
for(int i=1;i<n;i++)
{
if(grn[mc[i]]>0)
{
if(mc[i]+1<=n)
{
grn[mc[i]+1]++;
}
if(mc[i]-1>=1)
{
grn[mc[i]-1]++;
}
}
else
{
cout<<"NO"<<endl;
flag=false;
break;
}
}
if(flag)
{
cout<<"YES"<<endl;
}
}
return 0;
}
C
题意:给定一个数组,再给定几个字符串。这里规定一个数字对应唯一一个字符,一个字符对应唯一一个数字。判断字符串符不符合这样的规定。
#include<bits/stdc++.h>
using namespace std;
const int N=200010;
int a[N];
bool temp[200];
int mc[200];
int t,n,m;
bool solve(int x,string cr)
{
int tt=cr.size();
if(tt!=x)
return false;
else
{
set<int> kk;
kk.clear();
memset(temp,0,sizeof(temp));
memset(mc,0,sizeof(mc));
for(int i=0;i<cr.size();i++)
{
if(!temp[int(cr[i])])
{
temp[int(cr[i])]=true;
set<int>::iterator s;
bool p=true;
for(s=kk.begin();s!=kk.end();s++)
{
if(*s==a[i])
{
p=false;
break;
}
}
if(!p)
{
return false;
}
else
{
mc[int(cr[i])]=a[i];
kk.insert(a[i]);
}
}
else
{
if(a[i]!=mc[int(cr[i])])
return false;
}
}
return true;
}
}
int main()
{
cin>>t;
while(t--)
{
cin>>n;
for(int i=0;i<n;i++) cin>>a[i];
cin>>m;
string grn;
for(int i=0;i<m;i++)
{
cin>>grn;
if(solve(n,grn)) cout<<"YES"<<endl;
else cout<<"NO"<<endl;
}
}
return 0;
}
D
题意:给定一个数字和一个字符串。每次选择,一个l,一个r。把这里的数字加到总得分里。当然选过之后,这些里面的索引就再也不能用了。
特别的样例
做法:每次从外面判断,因为里面的一定会被外面所包裹。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=200010;
ll a[N],s[N];
char mc[N];
ll t,n;
int main()
{
cin>>t;
while(t--)
{
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>a[i];
s[i]=s[i-1]+a[i];
}
for(int i=1;i<=n;i++)
{
cin>>mc[i];
}
int temp=0;
for(int i=n;i>=1;i--)
{
if(mc[i]=='R')
{
temp=i;
break;
}
}
ll ans=0;
for(int i=1;i<=n;i++)
{
if(i<temp&&mc[i]=='L')
{
ans+=(s[temp]-s[i-1]);
bool flag=true;
for(int j=temp-1;j>=1;j--)
{
if(mc[j]=='R')
{
temp=j;
flag=false;
break;
}
}
if(flag)
temp=0;
}
}
cout<<ans<<endl;
}
return 0;
}
E
题解:每次循环求出k*k的左上角坐标。再求出右下角坐标。用二维差分求出哪个格子被算的次数最多(用大根堆维护),身高同理。每次取出堆顶即可。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll t,n,m,k;
void solve()
{
cin>>n>>m>>k;
vector<vector<ll> > mc(n+10,vector<ll>(m+10,0));
for(int i=1;i+k-1<=n;i++)
{
for(int j=1;j+k-1<=m;j++)
{
int x=i,y=j;
int sx=i+k,sy=j+k;
mc[x][y]++;
mc[x][sy]--;
mc[sx][y]--;
mc[sx][sy]++;
}
}
priority_queue<ll>q;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
mc[i][j]+=mc[i-1][j]+mc[i][j-1]-mc[i-1][j-1];
q.push(mc[i][j]);
}
}
priority_queue<ll>q1;
int grn;
cin>>grn;
while(grn--)
{
ll cr;
cin>>cr;
q1.push(cr);
}
ll ans=0;
while(q1.size()&&q.size())
{
ans+=(q1.top()*q.top());
q1.pop();
q.pop();
}
cout<<ans<<endl;
}
int main()
{
cin>>t;
while(t--)
{
solve();
}
return 0;
}