比赛地址
B
题意:求使得两个字符串相同的最小操作次数
思路:分两种情况,第一种如果原来sb就是全0字符串,那么只需要打击一次空格即可操作完成,此时次数最少;第二种通过当前字符对应的已经翻转的次数及当前字符与目标字符异同来判断是否需要进行翻转,分奇数次和偶数次情况,具体见下方代码注释,这里还需要注意一下,还得判断一下通过单击空格以后进行对应字符串的翻转匹配是否会比前一种得到的操作次数更少,更少的话就采取这种,否则去前一种更优
//前面cnt是奇数那当前卡片状态肯定是已经改变了的,如果这个时候sa=sb,毫无疑问当前卡片是要改变的,cnt++,存下下标,否则的话
//无需改变;如果前面cnt是偶数,当前状态相同就是相同,无需改变,否则需要改变,存储下标,cnt++;0的时候要特殊判断
//注意单击使得全0的操作也可能使得次数最少,需要进行比较
#include<iostream>
#include<string>
#include<cstring>
using namespace std;
const int N=1e5+10;
int loca[N],locb[N];
int main()
{
int t;
cin>>t;
while(t--){
string sa,sb,sc="";
cin>>sa>>sb;
int len=sb.size();
bool flag=true;
for(int i=0;i<len;i++){
if(sb[i]=='1'){
flag=false;
break;
}
}
if(flag){
cout<<0<<endl;
continue;
}
sc.append(len,'0');
memset(loca,0,sizeof(loca));
memset(locb,0,sizeof(locb));
int cnt1=0,cnt2=0,ta=0,tb=0;
locb[tb++]=0;
for(int i=0;i<len;i++){
if(cnt1%2){
if(sb[i]==sa[i])loca[ta++]=i+1,cnt1++;
}else if(cnt1%2==0&&cnt1){
if(sb[i]!=sa[i])loca[ta++]=i+1,cnt1++;
}
if(sa[i]!=sb[i]){
if(!cnt1)loca[ta++]=i+1,cnt1++;
}
}
for(int i=0;i<len;i++){
if(cnt2%2){
if(sb[i]==sc[i])locb[tb++]=i+1,cnt2++;
}else if(cnt2%2==0&&cnt2){
if(sb[i]!=sc[i])locb[tb++]=i+1,cnt2++;
}
if(sc[i]!=sb[i]){
if(!cnt2)locb[tb++]=i+1,cnt2++;
}
}
if(ta>tb){
for(int i=0;i<tb;i++)cout<<locb[i]<<' ';
if(tb==0)cout<<0;
cout<<endl;
}else{
for(int i=0;i<ta;i++)cout<<loca[i]<<' ';
if(ta==0)cout<<0;
cout<<endl;
}
}
return 0;
}
C
思路:区间查询,对每个区间尽可能选择距当前温度近的,贪心
#include<iostream>
#include<cstring>
using namespace std;
typedef long long ll;
const int N=1e5+10;
ll l[N],r[N];
int main()
{
int t;
scanf("%d",&t);
while(t--){
int n;
scanf("%d",&n);
memset(l,0,sizeof(l));
memset(r,0,sizeof(r));
for(int i=0;i<n;i++)scanf("%lld%lld",&l[i],&r[i]);
ll ans=n,res=0;
for(int i=0;i<n;i++){
if(l[i]>res){
ans+=(l[i]-res);
res=l[i];
}else if(r[i]<res){
ans+=(res-r[i]);
res=r[i];
}
}
printf("%lld\n",ans);
}
return 0;
}
F 签到题
#include<iostream>
#include<string>
#include<map>
using namespace std;
int main()
{
cout<<'e'<<endl;
return 0;
}
H
题意:每次读入一个区间,删除对应区间内的数,输出此时序列中剩下的数中的最大值
思路:线段树,因为这题数据范围m到1e5如果每次询问都遍历一遍区间寻找答案的话肯定是不行的,想要实现对区间的快速修改以及结果询问应当使用线段树
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<vector>
#define INF 0x3f3f3f3f
using namespace std;
typedef long long ll;
const int N=4e5+10;
ll a[N];
struct node{
int l,r;
ll mx,vis;
}tree[N];
void PushUp(int root)
{
tree[root].mx=max(tree[root<<1].mx,tree[root<<1|1].mx);
}
void Build(int l,int r,int root)
{
tree[root].l=l,tree[root].r=r,tree[root].vis=0;
if(l==r){
tree[root].mx=a[l];
return;
}
int mid=(l+r)>>1;
Build(l,mid,root<<1);
Build(mid+1,r,root<<1|1);
PushUp(root);
}
void PushDown(int root)
{
if(tree[root].vis){
tree[root<<1].mx=tree[root<<1|1].mx=0;
tree[root<<1].vis=tree[root<<1|1].vis=1;
tree[root].vis=0;
}
}
void Update(int L,int R,int root)
{
if(L<=tree[root].l&&tree[root].r<=R){
tree[root].mx=0;
tree[root].vis=1;
return;
}
PushDown(root);//下推标记
int mid=(tree[root].l+tree[root].r)>>1;
if(L<=mid)Update(L,R,root<<1);
if(R>mid)Update(L,R,root<<1|1);
PushUp(root);
}
ll Query(int L,int R,int root)
{
if(L<=tree[root].l&&tree[root].r<=R)return tree[root].mx;
PushDown(root);
int mid=(tree[root].l+tree[root].r)>>1;
ll _max=0;
if(L<=mid)_max=max(Query(L,R,root<<1),_max);
if(R>mid)_max=max(Query(L,R,root<<1|1),_max);
return _max;
}
int main()
{
int t;
scanf("%d",&t);
while(t--){
int n,m;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)scanf("%lld",&a[i]);
Build(1,n,1);
int L,R;
while(m--){
scanf("%d%d",&L,&R);
Update(L,R,1);
printf("%lld\n",tree[1].mx);
}
}
return 0;
}
I 签到题
#include<iostream>
using namespace std;
int main()
{
int t;
cin>>t;
while(t--){
int n;
cin>>n;
if(n>2)cout<<"Yes"<<endl;
else cout<<"No"<<endl;
}
return 0;
}
K
思路:暴力判断回文串,在符合回文的情况下还要符合年月日要求,注意判断闰年和2月
#include<iostream>
#include<string>
#include<map>
#include<algorithm>
using namespace std;
//判断闰年,闰年2月29天,平年28天
bool is_leap(int year)
{
if((year%4==0&&year%100!=0)||(year%400==0))return true;
return false;
}
//判断月份,大月31天,小月30天,2月特判
int days(int month,int year)
{
int day;
if(month==1||month==3||month==5||month==7||month==8||month==10||month==12)day=31;
else if(month==2){
if(is_leap(year))day=29;
else day=28;
}else day=30;
return day;
}
int main()
{
string s;
while(getline(cin,s)&&s[0]!='#'){
int cnt=0;
/*
for(int i=0;i<s.length();i++){
if(s[i]==' ')s.erase(i,1);
}
*/
int n=8;
for(int i=0;i<s.length();i++){
bool flag=true;
int len=0;
for(int j=0;j<n;j++){
if(s[i+j]!=s[i+n-j-1]){
flag=false;
break;
}
len++;
}
if(len!=8)flag=false;
int y=0,m=0,d=0;
if(flag){
for(int j=i;j<4+i;j++)y=y*10+s[j]-'0';
for(int j=i+4;j<6+i;j++)m=m*10+s[j]-'0';
for(int j=i+6;j<n+i;j++)d=d*10+s[j]-'0';
//cout<<y<<' '<<m<<' '<<d<<endl;
int day=days(m,y);
if((y>=1&&y<=9999)&&(m>=1&&m<=12)&&(d>=1&&d<=day))flag=true;
else flag=false;
if(flag)cnt++;
}
}
cout<<cnt<<endl;
}
return 0;
}