菜鸡每日刷题。
写题好慢,五道题能写好几小时,以后要限时写。
参考思路
char cl[2]={'W','B'};
void solve(){
int n,m;
cin>>n>>m;
vector<int>r(n+1,0),c(m+1,0);
vector<vector<char>>a(n+1,vector<char>(m+1));
vector<vector<int>>ans(n+1,vector<int>(m+1,-1));
forr(i,1,n){
string s;cin>>s;
forr(j,1,m){
a[i][j]=s[j-1];
if(s[j-1]!='.')c[j]++,r[i]++;
}
}
forr(i,1,n)if(r[i]%2!=0)return cout<<-1<<endl,void();
forr(i,1,m)if(c[i]%2!=0)return cout<<-1<<endl,void();
forr(i,1,n){
int x=0;
forr(j,1,m){//横向遍历
if(a[i][j]=='U'){//遍历到一个骨牌的上部
ans[i][j]=x;
ans[i+1][j]=ans[i][j]^1;//下部由上部决定
x=x^1;
}
}
}
forr(j,1,m){
int x=0;
forr(i,1,n){//纵向遍历
if(a[i][j]=='L'){//左部
ans[i][j]=x;
ans[i][j+1]=ans[i][j]^1;//决定右部
x=x^1;
}
}
}
forr(i,1,n){
forr(j,1,m){
if(ans[i][j]==-1)cout<<'.';
else cout<<cl[ans[i][j]];
}
cout<<endl;
}
}
题意:
思路
void solve(){
int n,k;
cin>>n>>k;
vector<int>a(n+1);
set<int>s;
forr(i,1,n){
cin>>a[i];
s.insert(a[i]);
}
if(k==1){//特判
if(s.size()>1)return cout<<-1<<endl,void();
else return cout<<1<<endl,void();
}else if(k>1){//可以是多种数字
s.clear();
int ans=0,fg=1,i=1;
while(i<=n){
int now=a[i];
s.insert(now);
while (i<=n&&a[i]==now)i++;//消除重复数字 (也可以用unique处理数组
if((s.size()==k)||(i>n)){//到最后位置(i>n) 没满k个也放进答案
s.clear();
s.insert(0);//前面的数收割完了 之后的b这个位置就是0 占一个种类
ans++;
}
}
// if(!s.empty()&&s.size()<=(fg==1?k-1:k)){
// // cout<
// s.clear();
// fg=1;
// ans++;
// }
cout<<ans<<endl;
}
}
void solve(){
int n,m,q;//n内部 m外部
cin>>n>>m>>q;
//一开始非得扯上角度 麻烦了 其实角度可以消掉
// int g=__gcd(360/n,360/m);
// // cout<
// int lcm=360*360/(n*m*g);
// if(lcm>=360)fg=1;
// int ig=lcm*n/360,og=lcm*m/360;
int g=__gcd(n,m);//分几组
int ig=n/g,og=m/g;//一组几个
forr(i,1,q){
int sx,sy,ex,ey;
cin>>sx>>sy>>ex>>ey;
if(g==1){
cout<<"YES"<<endl;
continue;
}
int scnt=(sy-1)/(sx==1?ig:og),ecnt=(ey-1)/(ex==1?ig:og);
if(scnt==ecnt)cout<<"YES"<<endl;
else cout<<"NO"<<endl;
}
}
void solve(){
int n;
cin>>n;
string a,b;
cin>>a>>b;
//相同 相异
int xor0=1,xor1=1;
forr(i,0,n-1){
if(a[i]==b[i])xor1=0;//不是相异
else xor0=0;
}
// cout<
//判断
if(!xor0&&!xor1)return cout<<"NO"<<endl,void();
cout<<"YES"<<endl;
//开始构造
int ans=0;vector<pair<int,int>>res;
if(xor1){//相异
forr(i,0,n-1){
if(a[i]=='1'){
ans++;
res.push_back({i+1,i+1});
}
}
if(ans%2==0){//相异
res.push_back({1,1});
res.push_back({2,n});
res.push_back({1,n});
}
}
else if(xor0){//相同
forr(i,0,n-1){
if(a[i]=='1'){
ans++;
res.push_back({i+1,i+1});
}
}
if(ans%2){//现在相异
res.push_back({1,1});
res.push_back({2,n});
res.push_back({1,n});
}
}
cout<<res.size()<<endl;
for(auto x:res)cout<<x.first<<' '<<x.second<<endl;
}
感觉是很简单的找规律题,但是对我这种菜鸡来说,想对思路需要耗费很长时间。
参考思路
实际上,如果一个子串满足条件,那么一个必要条件就是子串左侧没有与该子串左端一样的数字并且子串右侧也没有与该子串右端一样的数字。
可以发现,这个条件也是子串符合题意得充分条件。
如果满足这个条件,那么左侧一定没有第二种选法可以获得这个子串的前缀,同理右侧也无法获得这个子串的后缀,所以一定没有第二种选法可以获得这个字串。
所以,我们可以根据这个充要条件去找答案。
void solve(){
map<int,int>cnt;
int n;cin>>n;
vector<int>a(n+1),v(n+1,0);//v记录从前往后 有几个第一次出现的数字
forr(i,1,n)cin>>a[i];
forr(i,1,n){
if(cnt.count(a[i])==0){//从前往后 第一次出现
v[i]=v[i-1]+1;
cnt[a[i]]=1;
}else{
v[i]=v[i-1];
}
}
// forr(i,1,n)cout<
cnt.clear();
int k=0;
reforr(i,1,n){
if(cnt.count(a[i])==0){//从后往前 第一次出现
k+=v[i];
cnt[a[i]]=1;
}
}
cout<<k<<endl;
}