Codeforces Round #423 Div. 2-专题

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

A:水题不懂的看下代码就懂了

#include<algorithm>
#include<cstdio>
#include<string>
#include<cstring>
#include<iostream>
#include<cmath>
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define inf 0x3f3f3f3f
using namespace std;
typedef long long ll;
const int mx = 2e6+100;
int n,m,q;
int main(){
	while(~scanf("%d%d%d",&n,&m,&q)){
		int ans = 0,cnt = 0,v;
		while(n--){
			scanf("%d",&v);
			if(v==1){
				if(m==0){
					if(q==0){
						if(cnt) cnt--;
						else ans+=v;
					}else{
						q--;
						cnt++;
					}
				}else m--;
			}else{
				if(q==0) ans+=v;
				else q--;
			}
		}
		printf("%d\n",ans);
	}
	return 0;
} 
B题:找到最低最高最左最右差值取max比较一下。代码写的比较丑

#include<algorithm>
#include<cstdio>
#include<string>
#include<cstring>
#include<iostream>
#include<cmath>
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define inf 0x3f3f3f3f
using namespace std;
typedef long long ll;
const int mx = 1e2+100;
int n,m,q;
char str[mx][mx];
int main(){
	while(~scanf("%d%d%d",&n,&m)){
		int high=0,low=0,right=0,left=0,cnt = 0;
		for(int i=0;i<n;i++){
			scanf("%s",str[i]);
			for(int j=0;j<m;j++)
			if(str[i][j]=='B') cnt++;
		}
		for(int i=0;!high&&i<n;i++)
		for(int j=0;!high&&j<m;j++)
		if(str[i][j]=='B') high = i+1;
		
		for(int i=n-1;!low&&i>=0;i--)
		for(int j=0;!low&&j<m;j++)
		if(str[i][j]=='B') low = i+1;
		
		for(int j=0;!left&&j<m;j++)
		for(int i=0;!left&&i<n;i++)
		if(str[i][j]=='B') left = j+1; 
		
		for(int j=m-1;!right&&j>=0;j--)
		for(int i=0;!right&&i<n;i++)
		if(str[i][j]=='B') right = j+1;
		
		int maxx=max(right-left,low-high)+1;
		if(!cnt) puts("1");
		else if(maxx>min(n,m)) puts("-1");
		else printf("%d\n",maxx*maxx-cnt);
	}
	return 0;
}
C题: 并查集维护没有填入的点就行了。

#include<algorithm>
#include<cstdio>
#include<string>
#include<cstring>
#include<iostream>
#include<cmath>
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define inf 0x3f3f3f3f
using namespace std;
typedef long long ll;
const int mx = 3e6+100;
int n,m,q,f[mx];
char str[mx],ans[mx];
int find(int x){
	return x==f[x]? x:f[x]=find(f[x]);
} 
int main(){
	while(~scanf("%d",&n)){
		memset(ans,'a',sizeof(ans));
		for(int i=1;i<mx;i++) f[i]=i;
		int maxx = 0;
		while(n--){
			scanf("%s%d",str,&m);
			int len = strlen(str);
			while(m--){
				scanf("%d",&q);
				maxx = max(q+len,maxx);
				for(int i=find(q);i<q+len;i=f[i]=find(i+1))
				ans[i] = str[i-q];
			}
		}
		ans[maxx] = '\0';
		puts(ans+1);
	}
	return 0;
} 
D题:创建一个父节点,让他有m个孩子节点,然后m个孩子的孩子个只延伸一个。这就是最优方案。然后求节点高度就行了。

#include<algorithm>
#include<cstdio>
#include<string>
#include<cstring>
#include<iostream>
#include<cmath>
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define inf 0x3f3f3f3f
using namespace std;
typedef long long ll;
const int mx = 2e6+100;
int n,m,q;
int main(){
	while(~scanf("%d%d",&n,&m)){
		int k =(n-1)/m,mod = (n-1)%m;
		if(mod>=2) k = 2*(k+1);
		else if(mod==1)  k = 2*k+1;
		else k = 2*k;
		printf("%d\n",k);
		for(int i=2;i<=m+1;i++) printf("1 %d\n",i);
		int j = m+2;
		for(int i=2;j<=n;j++,i++){
			printf("%d %d\n",i,j);
		}
	}
	return 0;
} 
E题:我们发现e字符串很短也就是某个i点能向后延伸1-10个步长。延伸的起点也只可能是1-10这前十个点。又有4个字母那么我们应该需要维护的是一个sum[x][y][z][q],代表起点,步长,哪个字母,从该起点以这种步长走到q有了几个z字母。数组大小差不多为sum【11】【11】【4】【10^5+10】,然后就是树状数组维护就行了,不会很麻烦。
#include<algorithm>
#include<cstdio>
#include<string>
#include<cstring>
#include<iostream>
#include<cmath>
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define inf 0x3f3f3f3f
using namespace std;
typedef long long ll;
const int mx = 1e5+10;
int n,m,q;
int sum[11][11][4][mx],lens;
char str[mx],c[20];
inline int lowbit(int x){
	return x&(-x);
}
int getnum(char c1){
	switch(c1){
		case 'A':return 0;
		case 'T':return 1;
		case 'G':return 2;
		case 'C':return 3;
	}
}
void add(int s,int x,int y,int z,int v){
	for(int i = s;i<=lens;i+=lowbit(i))
	sum[x][y][z][i] += v;
}
void update(int x,int k,int v){
	for(int j=1;j<=10;j++){
		int p = x%j;
		if(!p) p = j;
		add(x,p,j,k,v);
	}	
}
int query(int x,int y,int k,int s){
	int ans = 0;
	while(s){
		ans+=sum[x][y][k][s];
		s-=lowbit(s);
	}
	return ans;
}
int main(){
	while(~scanf("%s",str+1)){
		memset(sum,0,sizeof(sum));
		scanf("%d",&n);
		lens = strlen(str+1);
		for(int i=1;i<=lens;i++){
			int k = getnum(str[i]);
			update(i,k,1);
		}
		int x,y,z;
		while(n--){
			scanf("%d",&x);
			if(x==1){
				scanf("%d%s",&y,c);
				update(y,getnum(str[y]),-1);
				update(y,getnum(c[0]),1);
				str[y] = c[0];
			}else{
				scanf("%d%d%s",&y,&z,c);
				int len = strlen(c),ans = 0;
				for(int i=0;i<len;i++){
					int p = (i+y)%len;
					if(!p) p = len;
					ans += query(p,len,getnum(c[i]),z)-query(p,len,getnum(c[i]),y-1); 
				}
				printf("%d\n",ans);
			}
		}
	}
	return 0;
} 






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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值