Codeforces Round #424 Div. 2专题

38 篇文章 0 订阅
19 篇文章 0 订阅

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就行了多了也是重复,在这面找答案就行了。

 



 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值