Codeforces Round #637 (Div. 2) - Thanks, Ivan Belonogov! Solution

AA

int T,n,a,b,c,d,m,st,ed,l,r;

int main() {
	qr(T); for(int t=1;t<=T;t++) {
		qr(n); qr(a); qr(b); qr(c); qr(d);
		st=a-b; ed=a+b; l=c-d; r=c+d; 
		if(st*n>r||ed*n<l) {puts("NO"); continue;}
		puts("YES");
	}
	
	return 0;
}

BB

前綴和

int T,k,n,a[N],s[N],ans,pos;

int main() {
	qr(T); while(T--) {
		 qr(n);qr(k);
		for(int i=1;i<=n;i++) 
			qr(a[i]);
		for(int i=2;i<n;i++) {
			if(a[i-1]<a[i]&&a[i]>a[i+1]) s[i]=1;
			else s[i]=0;
			s[i]+=s[i-1];
		}
		pos=1;ans=0;
		for(int i=1;i+k-1<=n;i++) 
			if(ans<s[i+k-2]-s[i]) ans=s[i+k-2]-s[i],pos=i;
		pr1(ans+1); pr2(pos);
	}
	return 0;
}

CC

一個合法的排列類似:

5 3 4 1 2

從1開始往右掃直到碰到第n+1個位置或者已經訪問過的位置,此時跳到應該掃描的位置並重復操作.

如上例:掃描1 2,掃描3 4,掃描5

如果不能掃描完全則輸出-1.

int T,n,a[N],ans,vis[N],num,p[N],now;

int main() {
	qr(T); while(T--) {
		qr(n); vis[n+1]=++num;
		for(int i=1;i<=n;i++) qr(a[i]),p[a[i]]=i;
		now=p[1]-1; ans=1;
		for(int i=1;i<=n;i++)
			if(p[i]==now+1) vis[p[i]]=num,now++;
			else if(vis[now+1]==num) vis[now=p[i]]=num;
			else {ans=0; break;}
		puts(ans?"YES":"NO");
	}
	return 0;
}

DD

考察簡單的DP+狀態壓縮.

f[i][j]f[i][j]表示[i,n]j[i,n]選擇j個額外的棒子最大數的當前ii位選擇的數.

保障最大的措施是從後往前枚舉和數字從小到大枚舉.

int n,m,f[N][N],pre[N][N],a[N],cnt[N],num[11]={119,18,93,91,58,107,111,82,127,123,};
char s[N];

int g(char *s) {
	int y=0;
	for(int i=0;i<7;i++) y=y*2+(s[i]-'0');
	return y;
}

bool pd(int x,int y) {return ((x&num[y])==x);}//x->y 

int main() {
	for(int i=1;i<=(1<<7);i++)cnt[i]=cnt[i&(i-1)]+1;
	qr(n); qr(m); memset(f,-1,sizeof f);
	for(int i=1;i<=n;i++) {
		scanf("%s",s);
		a[i]=g(s);
	}
	for(int i=0,j;i<=9;i++) if(pd(a[n],i)) f[n][cnt[num[i]^a[n]]]=i;
	for(int i=n-1;i>0;i--) {
		for(int j=0,k;j<=9;j++)
			if(pd(a[i],j)) {
				k=cnt[num[j]^a[i]];
				for(int x=k;x<=m;x++)
					if(f[i+1][x-k]!=-1) {
						f[i][x]=j;
						pre[i][x]=x-k;
					}
			}
	}
	if(f[1][m]==-1) puts("-1");
	else {
		int x=m;
		for(int i=1;i<=n;i++)
			qw(f[i][x]),x=pre[i][x];
	}
	return 0;
}

EE

mm輪搜索即可.
複雜度大概爲O(m2)O(m^2)

#include<bits/stdc++.h>
#define pb push_back
using namespace std;
const int N=10010,G=1010;
int x[N],n,m,r,g,ans=2e9;
bool v[N][G];
vector<int> q[N];
void dfs(int now,int u,int t) {
	if(u<1||u>m||t<0||v[u][t]) return ;
	v[u][t]=1;
	if(u==m) ans=min(ans,now*(g+r)+g-t);
	if(!t) q[now+1].pb(u);
	else {
		dfs(now,u-1,t-(x[u]-x[u-1]));
		dfs(now,u+1,t-(x[u+1]-x[u]));
	}
}
void qr(int &x) {scanf("%d",&x);}
int main() {
	qr(n); qr(m);
	for(int i=1;i<=m;i++) qr(x[i]);
	qr(g); qr(r);
	sort(x+1,x+m+1); q[0].pb(1);
	for(int i=0;i<=m;i++) {
		for(int j:q[i]) dfs(i,j,g);
		if(ans!=2e9) {printf("%d\n",ans); exit(0);}
	}
	puts("-1");
	return 0;
}

FF

orz mayaohua

#include<cstdio>
#include<vector>
#define pi pair<int,int>
using namespace std;
const int N=1e6+10;

vector<int>e[N];
int n,m,cnt,deg[N];
pi ans[N*3];

void dfs(int x,int t,int f) {
	int fir=t;
	ans[++cnt]=pi(x,t);
	for(int y:e[x]) if(y^f) {
		if(t==m) {
			t=m-deg[x];
			ans[++cnt]=pi(x,t);
		}
		dfs(y,++t,x);
		ans[++cnt]=pi(x,t);
	}
	if(t!=fir-1&&x>1) ans[++cnt]=pi(x,fir-1);//保障回溯時爲fir-1 
}

void add(int x,int y) {deg[x]++; e[x].push_back(y);}

int main() {
	scanf("%d",&n);
	for(int i=1,x,y;i<n;i++)
		scanf("%d %d",&x,&y),add(x,y),add(y,x);
	for(int i=1;i<=n;i++) m=max(m,deg[i]);//最大的t值顯然爲maxdeg 
	dfs(1,0,0);printf("%d\n",cnt);
	for(int i=1;i<=cnt;i++) printf("%d %d\n",ans[i].first,ans[i].second);
	return 0;
}

GG

蠻有意思的題目.

簡明題意:三人圍剿入侵者.連通圖中每個點的度數<4,且每個環的長度<6.

顯然最後一個移動前大概爲這樣的情況.

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-4TNVrcUb-1587724574343)(C:\Users\Administrator\Desktop\2020 04 23 CF\image-20200424182440982.png)]

然後,我就想不出來了.

只是覺得應該往靠近的方向跑.

看完題解後,發現這是個簡單的最短路.

把邊雙壓成一個點,就會形成一棵樹.

在n步範圍內一定可以追到.

於是可以得到這樣的代碼:

#include<cstdio>
#include<vector>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=5010;

int n,m,x,pos[3]={1,2,3},d[N][N];
vector<int> tmp(3),now(3),res(3),e[N];
void add(int x,int y) {e[x].push_back(y);}

int q[N];
void spfa(int *d,int st) {
	int l=1,r=1; q[1]=st; d[st]=0;
	while(l<=r) {
		int x=q[l++];
		for(int i=e[x].size()-1,y;i>=0;i--) {
			y=e[x][i];
			if(y^st&&!d[y])
				d[y]=d[x]+1,q[++r]=y;
		}
	}
}

void get(int p,int x,int y,int z) {
	now[0]=now[1]=now[2]=N;
	for(int i=e[p].size()-1,t;i>=0;i--) { 
		t=e[p][i];
		spfa(d[t],t);
	}
	for(int i=0,a;i<e[x].size();i++) 
		for(int j=0,b;j<e[y].size();j++) if((a=e[x][i])^(b=e[y][j])) 
			for(int k=0,c;k<e[z].size();k++) if(c=e[z][k],(a^c)&&(b^c)) {//模擬運動方向 
				res[0]=res[1]=res[2]=0;
				for(int l=0,t;l<e[p].size();l++) {//模擬逃離方向 
					t=e[p][l];
					tmp[0]=d[t][a];
					tmp[1]=d[t][b];
					tmp[2]=d[t][c];
					sort(tmp.begin(),tmp.end());
					res=max(res,tmp);//對方的去向不確定,所以我們應該取最大值 
				}
				if(res<now) {
					now=res;//追得更近了 
					pos[0]=a;
					pos[1]=b;
					pos[2]=c;
				}
			}
}

int main() {
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++) add(i,i); 
	for(int i=1,y;i<=m;i++)
		scanf("%d%d",&x,&y),add(x,y),add(y,x);
	x=0;
	while(1) {
		printf("%d %d %d\n",pos[0],pos[1],pos[2]);
		fflush(stdout); 
		if(x==pos[0]||x==pos[1]||x==pos[2]) return 0;
		scanf("%d",&x);
		if(x==pos[0]||x==pos[1]||x==pos[2]) return 0;
		get(x,pos[0],pos[1],pos[2]);
	}
	return 0;
}

HH

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章