A题:波峰的时候可以连续相等否则其他不行。然后满足只有一个波峰或者单调就行了。
代码:
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <set>
#include <map>
#include <string>
#include <math.h>
#include <stdlib.h>
#include <time.h>
using namespace std;
const int mx = 1e2+10;
int n,m,a[mx];
int main(){
while(~scanf("%d",&n)){
int pos = 0,max = 0;
for(int i =1;i<=n;i++){
scanf("%d",a+i);
if(a[i]>max){
max = a[i];
pos = i;
}
}
for(int i=1;i<pos;i++){
if(a[i]>a[i+1]||(a[i]==a[i+1]&&a[i]!=max)){
puts("NO");
return 0;
}
}
for(int i=n;i>pos;i--){
if(a[i]>a[i-1]||(a[i]==a[i+1]&&a[i]!=max)){
puts("NO");
return 0;
}
}
puts("YES");
}
return 0;
}
B:给你两个键盘模式叫你互换就换一下26个字母就行了
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <set>
#include <map>
#include <string>
#include <math.h>
#include <stdlib.h>
#include <time.h>
using namespace std;
const int mx = 1e2+10;
int n,m,a[mx];
int id[26];
char c1[40],c2[40],c3[1100];
int main(){
while(~scanf("%s%s",c1,c2)){
for(int i=0;i<26;i++)
id[c1[i]-'a']=i;
scanf("%s",c3);
int len =strlen(c3);
for(int i=0;i<len;i++){
if(isdigit(c3[i])) putchar(c3[i]);
else if(isupper(c3[i])) putchar(c2[id[c3[i]+32-'a']]-32);
else putchar(c2[id[c3[i]-'a']]);
}
puts("");
}
return 0;
}
C:将连续序列和的数组排序,将最小的b[i]枚举到每个位置,然后看b2-bn的数是否都能找到相应的位置。
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <set>
#include <map>
#include <string>
#include <math.h>
#include <stdlib.h>
#include <time.h>
using namespace std;
const int mx = 2e3+10;
int n,m,a[mx],sum[mx],b[mx],cnt[mx];
int main(){
sum[0] = 0;
while(~scanf("%d%d",&n,&m)){
for(int i=1;i<=n;i++){
scanf("%d",a+i);
sum[i]=sum[i-1]+a[i];
cnt[i] = sum[i];
}
for(int i=1;i<=m;i++) scanf("%d",b+i);
sort(b+1,b+1+m);
sort(cnt+1,cnt+1+n);
int ans = 0,t=2;
sum[1] = cnt[1];
for(int i=2;i<=n;i++)
if(cnt[i-1]!=cnt[i]) sum[t++] = cnt[i];
for(int i=1;i<t;i++){
int flag=0,j = 2;
while(j<=m){
int po = b[j]-b[1]+sum[i];
int pos = lower_bound(cnt+1,cnt+1+n,po)-cnt;
if(pos==n+1||cnt[pos]!=po){
flag = 1;
break;
}
j++;
}
if(!flag) ans++;
}
printf("%d\n",ans);
}
return 0;
}
D:dp,贪心,二分都可以做。这里满足决策单调性直接贪心比较简单一点
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <set>
#include <map>
#include <string>
#include <math.h>
#include <stdlib.h>
#include <time.h>
using namespace std;
typedef long long ll;
const int mx = 2e3+10;
int n,m,q,a[mx],b[mx];
int sum[mx];
ll dis(int x,int y){ return abs(1ll*b[x]-1ll*a[y])+abs(1ll*b[x]-1ll*q); }
int main(){
while(~scanf("%d%d%d",&n,&m,&q)){
ll ans = 1e16;
memset(sum,0,sizeof(sum));
for(int i=1;i<=n;i++) scanf("%d",a+i);
for(int i=1;i<=m;i++) scanf("%d",b+i);
sort(a+1,a+1+n);
sort(b+1,b+1+m);
for(int i=1;i<=m-n+1;i++){
ll cnt = 0;
for(int j=1;j<=n;j++){
cnt = max(cnt,dis(i+j-1,j));
}
ans = min(cnt,ans);
}
cout << ans <<endl;
}
return 0;
}
E:将牌的排名从小到大枚举。假设排名i的值在牌堆最底下的位置是k那么当处理i+1的时牌堆状态应该是k-n加上1-(k-1)拼接而成。那么我接下来只需要去找在1-(k-1)中
排名i+1最底层的,如果找不到则在k-n中找。然后树状数组更新被删过的点就行了
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <set>
#include <map>
#include <string>
#include <math.h>
using namespace std;
typedef long long ll;
const int mx = 1e5+10;
int n,m,q,minn = 1e9;
vector<int> vec[mx];
ll sum[mx];
inline int lowbit(int x) { return x&(-x); }
void add(int x,int v){ for(int i=x;i<=n;i+=lowbit(i)) sum[i]+=v; }
ll getsum(int x){
ll ans = 0;
while(x){
ans += sum[x];
x -= lowbit(x);
}
return ans;
}
int main(){
while(~scanf("%d",&n)){
memset(sum,0,sizeof(sum));
for(int i=1;i<=n;i++) scanf("%d",&q), vec[q].push_back(i), add(i,1), minn = min(q,minn);
ll ans = getsum(vec[minn].back()),k = vec[minn].back();
for(int j=0;j<vec[minn].size();j++) add(vec[minn][j],-1);
for(int i=minn+1;i<mx;i++){
if(!vec[i].size()) continue;
auto it = lower_bound(vec[i].begin(),vec[i].end(),k);
if(it == vec[i].begin()) ans += getsum(*(it = --vec[i].end()))-getsum(k-1);
else ans += getsum(*(--it))+getsum(n)-getsum(k-1);
k = *it;
for(int j=0;j<vec[i].size();j++) add(vec[i][j],-1);
}
cout << ans <<endl;
}
return 0;
}
F:数学题。通过计算可得(C(所以的竹子限定长度和)+k)/SUM(每个竹子在某一天中没砍掉的天数和)>=d,那么我只需枚举i∈1-sqrt(C+k)还有(C+k)/i就行了多了也是重复,在这面找答案就行了。