A:​http://codeforces.com/contest/1400/problem/A

解析:

发现每一个字符串,都包含s[n-1],所以直接打印n个s[n-1]即可

#include<bits/stdc++.h>
#include<map>
#include<iostream>
#include<cstring>
#include<cmath>
using namespace std;
typedef long long ll;
const int maxn=1e5+10;
const int maxn2=1e9+10;
int answ[maxn];
int md[maxn];
int b[maxn];
int n,m;
int a[maxn];
int v[maxn];
struct node
{
int x1,y1,x2,y2;
}st[maxn];
int main()
{
int t;
cin>>t;
while(t--)
{
int n;
cin>>n;
string s;
cin>>s;
for(int i=1;i<=n;i++)
cout<<s[n-1];
cout<<endl;
}
}

 

B:​http://codeforces.com/contest/1400/problem/B

题意:

两个袋子大小:p,f

两种物品数量:c1,c2

两种物品所占空间:s,w

求能装的最大数量

解析:

贪心来讲,规定s<w,那么对于第一个袋子,尽量先放s,然后w,第二个袋子也是如此

根据这个贪心思路,可以对第一个袋子拿取的s数量进行枚举,s装好,再装w。c1,c2去掉之前的消耗,再对第二个袋子进行同样操作。

细节在注释里

#include<bits/stdc++.h>
#include<map>
#include<iostream>
#include<cstring>
#include<cmath>
using namespace std;
typedef long long ll;
const int maxn=1e5+10;
const int maxn2=1e9+10;
struct node
{
int x1,y1,x2,y2;
}st[maxn];
int main()
{
int t;
cin>>t;
while(t--)
{
ll p,f;
ll c1,c2,s,w;
cin>>p>>f>>c1>>c2>>s>>w;
ll maxx=0;  //这里并没有交换s,w,第一个袋子虽然应该优先装小的,但是下面的for已经枚举到了第一种袋子的所有可能
for(int i=0;i<=min(c1,p/s);i++)
{
ll s1,s2,s3;//i,s1为第一个袋子分别装s,w的数量。s2,s3分别为第二个袋子装s,w的数量
s1=(p-s*i);
s1=min(s1/w,c2);
if(s<=w)  //第二个袋子优先选小
{
if(f>=(c1-i)*s)  //还能再装s
{
s2=c1-i;
s3=min(c2-s1,(f-(c1-i)*s)/w);  
}
else
{
s2=f/s; 
s3=0;
}
}
else
{
if(f>=(c2-s1)*w)//还能再装w
{
s2=c2-s1;
s3=min(c1-i,(f-(c2-s1)*w)/s);
}
else
{
s2=0;
s3=f/w;
}
}
maxx=max(maxx,i+s1+s2+s3);
}
cout<<maxx<<endl;
}
}

C:​http://codeforces.com/contest/1400/problem/C

题意:

给出字符串s和整数x,求字符串w

s满足:

w[i+x]或w[i-x]为1,si为1,否则si为0

解析:

初始化w全为1。

遍历si的'0',把w[i]变成符合对应要求

再次遍历si的'1',如果w[i+x]==0&&w[i-x]==0,输出-1

#include<bits/stdc++.h>
#include<map>
#include<iostream>
#include<cstring>
#include<cmath>
using namespace std;
typedef long long ll;
const int maxn=1e5+10;
const int maxn2=1e9+10;
char s1[maxn],s2[maxn];
struct node
{
int x1,y1,x2,y2;
}st[maxn];
int main()
{
int t;
cin>>t;
while(t--)
{
int x;
cin>>s1>>x;
int le=strlen(s1);
for(int i=0;i<le;i++)
s2[i]='1';
for(int i=0;i<le;i++)
{
if(s1[i]=='0')
{
if(i>=x)
s2[i-x]='0';
if(i+x<le)
s2[i+x]='0';
}
}
int ok = 0;
for(int i=0;i<le;i++)
{
int ok1=0,ok2=0;
if(s1[i]=='1')
{
if(i>=x&&s2[i-x]=='1')
ok1=1;
if(i+x<le&&s2[i+x]=='1')
ok2=1;
if(!ok1&&!ok2)
{
ok=1;break;
}
}
}
if(ok)
cout<<"-1"<<endl;
else
{
for(int i=0;i<le;i++)
cout<<s2[i];
cout<<endl;
}
}
}

D:​http://codeforces.com/contest/1400/problem/D

题意:

数组ai,1<=i<j<k<l<=n,求ai=ak,aj=al的数量

解析:

枚举j,l。

假设aj==al

....aj....ax.....al,要想凑够满足题意的那四个,需要aj之前存在与ax相等的数,有几个,就能和aj,al凑成几个。所以就需要记录aj之前出现了几个ax

cnt[]记录aj之前的各个数字出现的次数。

要注意一下顺序问题,cnt[]是要在for的最后更新才行。

#include<bits/stdc++.h>
#include<map>
#include<iostream>
#include<cstring>
#include<cmath>
using namespace std;
typedef long long ll;
const int maxn=3e3+10;
const int maxn2=1e9+10;
char s1[maxn],s2[maxn];
int a[maxn];
ll cnt[maxn];
struct node
{
int x1,y1,x2,y2;
}st[maxn];
int main()
{
int t;
cin>>t;
while(t--)
{
memset(cnt,0,sizeof(cnt));
int n;
cin>>n;
for(int i=1;i<=n;i++)
cin>>a[i];
ll sum = 0 ;
for(int j=1;j<n;j++)
{
int md=0;
for(int l=j+1;l<=n;l++)
{
if(a[j]==a[l])
sum+=md;
md+=cnt[a[l]];
}
cnt[a[j]]++;
}
cout<<sum<<endl;
}
}

E:​http://codeforces.com/contest/1400/problem/E

题意:

给出数组

操作1:[L,R]集体减1

操作2:对任意一个数,把它变成比它自己小的任意一个数

把所有数归0的最小操作数

解析:

分治

之前做过。

[L,R]都变0的话,需要r-l+1步,

与集体减1那个操作取个min就可以了

#include<bits/stdc++.h>
#include<map>
#include<iostream>
#include<cstring>
#include<cmath>
using namespace std;
typedef long long ll;
const int maxn=5e3+10;
const int maxn2=1e9+10;
const int mod=1e9+10;
char s1[maxn],s2[maxn];
ll a[maxn];
ll cnt[maxn];
struct node
{
int x1,y1,x2,y2;
}st[maxn];
int ac(int l,int r)
{
if(l>r) return 0;
int minn=mod;
int k;
for(int i=l;i<=r;i++)
{
if(a[i]<minn)
{
minn=a[i];
k=i;
}
}
int md=a[k];
for(int i=l;i<=r;i++)
a[i]-=minn;
return min(r-l+1,md+ac(l,k-1)+ac(k+1,r));
}
int sum=0;
int main()
{
int n;
cin>>n;
for(int i=1;i<=n;i++)
cin>>a[i];
cout<<ac(1,n)<<endl;
// cout<<sum<<endl;