唉,有点可惜,感觉D题能做出来,可惜时间有点不够了…果然教育场被教育…
先写三个题的题解吧,剩下的慢慢补。
A就没什么好说的了,统计出最左和最右的位置看一下中间有多少0就行。
#include
using namespace std;
typedef long long ll;
const int maxn=100010,mod=1e9+7;
int main()
{
int t; cin>>t;
while(t--)
{
string s; cin>>s;
int res=0,l=-1,r=0,num=0;
for(int i=0;i<s.size();i++)
{
if(s[i]=='1')
{
num++;
if(l==-1) l=i;
r=i;
}
}
if(num==0)
cout<<0<<endl;
else
cout<<r-l+1-num<<endl;
}
return 0;
}
B是真的有那点坑,题面说的是修完整条路…修完整条路…思路直接看代码吧!还是比较简单的.
#include
using namespace std;
typedef long long ll;
int main()
{
ll t; cin>>t;
while(t--)
{
ll n,g,b; cin>>n>>g>>b;
ll tmp=(n+1)/2;
if(tmp<=g) //所需高质量比g小直接输出n就行
cout<<n<<endl;
else
{
ll num=tmp/g;
ll ans;
if(tmp%g==0) 等于0说明是有num-1个整周全再加g天
ans=(num-1)*(g+b)+g;
else
ans=(num)*(g+b)+tmp%g; 不等于0说明有num个周期再加剩余的几天
cout<<max(ans,n)<<endl;
}
}
return 0;
}
其实蒟蒻想到的是双向链表,但是忘了,2333,只能写成数组了。。。
手动模拟一下这个题就会发现有个规律,他每次都是在某个数的左右移动才行。
就像这个样例:zxzytyz。z先放,然后x!=z,所以x放在z右边,再看下一个z,因为等于当前位置-1的那个字母,所以直接让当前位置-1,而不需要的添加新的位置,以此类推,(假设当前位置为ans),每次判断ans,ans-1,ans+1;相等的话就让当前位置++,–,或不变。
#include
using namespace std;
typedef long long ll;
char str[205],ans[105];
bool vis[105];
int main()
{
int T; scanf("%d",&T);
while (T--)
{
scanf("%s",str+1);
int n=strlen(str+1),l=27,r=27,now=27,flag=0;
ans[l]=str[1];
memset(vis,0,sizeof(vis));
vis[str[1]-'a']=1;
for (int i=2;i<=n;i++)
{
if (now>l&&ans[now-1]==str[i])
now--;
else if (now<r&&ans[now+1]==str[i])
now++;
else if (now==l&&!vis[str[i]-'a'])
ans[--l]=str[i],now--,vis[str[i]-'a']=1;
else if (now==r&&!vis[str[i]-'a'])
ans[++r]=str[i],now++,vis[str[i]-'a']=1;
else
{
flag=1;
break;
}
}
if (flag)
puts("NO");
else
{
puts("YES");
for (int i=l;i<=r;i++)
putchar(ans[i]);
for (int i=0;i<26;i++)
if (!vis[i]) putchar(i+'a');
puts("");
}
}
return 0;
}
上面是大佬的代码,如果不理解可以看一下蒟蒻的代码,真的是不好意思放出来…
#include
using namespace std;
typedef long long ll;
const ll mod = 1e9+7;
const int N = 2e5+5;
int a[600];
int b[60];
int main()
{
ll t;cin>>t;
while(t--)
{
memset(a,-1,sizeof a);
memset(b,-1,sizeof b);
string s;cin>>s;
a[300]=s[0]-'a';
int x=300;
int flag=1;
for(int i=1;i<s.size();i++) //直接处理字符串然后存入一个数组中
{
if((s[i]-'a')!=a[x-1]&&(s[i]-'a')!=a[x+1]&&(s[i]-'a')!=a[x])
{
if(a[x+1]!=-1&&a[x-1]!=-1)
{
flag=0;
break;
}
if(a[x+1]==-1)
{
x++;
a[x]=s[i]-'a';
}
if(a[x-1]==-1)
{
x--;
a[x]=s[i]-'a';
}
}
else if((s[i]-'a')==a[x-1])
x--;
else if((s[i]-'a')==a[x+1])
x++;
}
if(!flag)
cout<<"NO"<<endl;
else
{
set<int> st;
for(int i=0;i<600;i++) //判断是不是有重复元素
{
if(a[i]!=-1)
{
if(st.count(a[i]))
flag=0;
else
st.insert(a[i]);
}
}
if(!flag)
cout<<"NO"<<endl;
else
{
cout<<"YES"<<endl;
for(int i=0;i<600;i++)//没有的话顺序输出数组里面的东西,然后再将剩下的输出
{
if(a[i]!=-1)
{
cout<<char(a[i]+'a');
b[a[i]]=1;
}
}
for(int i=0;i<26;i++)
if(b[i]==-1)
cout<<char(i+'a');
cout<<endl;
}
}
}
return 0;
}
妈耶,真的是第一印象二进制一直往二进制那方面想…虽然也能写出来但是真的是不如贪心来的舒服,直接看代码吧,思路一眼就能看出来.
#include
using namespace std;
typedef long long ll;
int main()
{
int t;cin>>t;
while (t--)
{
ll s,n,m,x,ans;
cin>>n>>m;
s=ans=0;
multiset<ll,greater<ll>> f;
while (m--)
{
cin>>x;
s+=x;
f.insert(x);
}
if (s<n)//和都小于n了,还分解啥呀...
cout<<"-1"<<endl;
else
{
while(n)
{
m=*f.begin();
f.erase(f.begin());
if(m<=n) //m<=n不用分解,直接减去
{
n-=m;
s-=m;
}
else if(s-m<n) //除了m剩下的
{
ans++;
f.insert(m/2);
f.insert(m/2);
}
else //剩下的m>n&&s-m>n,这种情况要不要m都无所谓
s-=m;
}
cout<<ans<<endl;
}
}
}
E感觉能DP出来,待补吧…FG就算了,还是继续保命…
能出来个鬼,写了一中午不是最后一个大大的WA,差点我自己就信了…