本文主要是介绍Codeforces Round #245 (Div. 1) ABCDE,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
赛前随便选了一场 CF Div 1
一棵树,每个点上可以是0或者1.对某个点的一次操作可以使自己,自己孙子,自己孙子的孙子....的权值翻转,求最少翻转多少次和翻转的点编号。
dfs,贪心地尽量翻转深度小的点即可。
#include <cstdio>
#include <iostream>
#include <string.h>
#include <string>
#include <map>
#include <queue>
#include <deque>
#include <vector>
#include <set>
#include <algorithm>
#include <math.h>
#include <cmath>
#include <stack>
#include <iomanip>
#define mem0(a) memset(a,0,sizeof(a))
#define meminf(a) memset(a,0x3f,sizeof(a))
using namespace std;
typedef long long ll;
typedef long double ld;
typedef double db;
const int maxn=100005,inf=0x3f3f3f3f;
const ll llinf=0x3f3f3f3f3f3f3f3f;
const ld pi=acos(-1.0L);
int head[maxn],a[maxn],b[maxn];
bool visit[maxn];
int num,ans;
vector<int> v;struct Edge {int from, to, pre;
};
Edge edge[maxn*2];void addedge(int from, int to) {edge[num] = (Edge) {from, to, head[from]};head[from] = num++;edge[num] = (Edge) {to, from, head[to]};head[to] = num++;
}void dfs(int now,int s1,int s2) {visit[now]=1;int flag=0;if (a[now]^s2!=b[now]) ans++,flag=1,v.push_back(now);for (int i=head[now];i!=-1;i=edge[i].pre) {int to=edge[i].to;if (!visit[to])dfs(to,s2^flag,s1);}
}int main() {int n,x,y,i,j;scanf("%d",&n);num=0;memset(head,-1,sizeof(head));for (i=1;i<n;i++) {scanf("%d%d",&x,&y);addedge(x,y);}for (i=1;i<=n;i++) scanf("%d",&a[i]);for (i=1;i<=n;i++) scanf("%d",&b[i]);mem0(visit);ans=0;dfs(1,0,0);printf("%d\n",ans);for (i=0;i<v.size();i++) {printf("%d\n",v[i]);}return 0;
}
这题有点像经典题传纸条。
一个矩阵,两个人中其中一个从左上到右下,另一个左下到右上。显然两人的路径会相遇一次,相遇格子的价值不计,其余格子的价值计算一次,问两个人所走路径的权值和最大是多少。
DP。先预处理从四个角到某点的最大权值和,再枚举相遇的格子,用四个方向到这个格子的最大权值加起来更新答案。
#include <cstdio>
#include <iostream>
#include <string.h>
#include <algorithm>
using namespace std;
typedef long long ll;
const int maxn=1005;
ll dp[5][maxn][maxn];
ll a[maxn][maxn];int main() {int n,m,i,j,k;scanf("%d%d",&n,&m);memset(dp,0,sizeof(dp));for (i=1;i<=n;i++) {for (j=1;j<=m;j++) {scanf("%lld",&a[i][j]);}}dp[1][1][1]=a[1][1];for (i=1;i<=n;i++) {for (j=1;j<=m;j++) {dp[1][i+1][j]=max(dp[1][i+1][j],dp[1][i][j]+a[i+1][j]);dp[1][i][j+1]=max(dp[1][i][j+1],dp[1][i][j]+a[i][j+1]);// cout << dp[1][i][j] << endl;}}dp[2][1][m]=a[1][m];for (i=1;i<=n;i++) {for (j=m;j>=1;j--) {dp[2][i+1][j]=max(dp[2][i+1][j],dp[2][i][j]+a[i+1][j]);dp[2][i][j-1]=max(dp[2][i][j-1],dp[2][i][j]+a[i][j-1]);}}dp[3][n][1]=a[n][1];for (i=n;i>=1;i--) {for (j=1;j<=m;j++) {dp[3][i-1][j]=max(dp[3][i-1][j],dp[3][i][j]+a[i-1][j]);dp[3][i][j+1]=max(dp[3][i][j+1],dp[3][i][j]+a[i][j+1]);}}dp[4][n][m]=a[n][m];for (i=n;i>=1;i--) {for (j=m;j>=1;j--) {dp[4][i-1][j]=max(dp[4][i-1][j],dp[4][i][j]+a[i-1][j]);dp[4][i][j-1]=max(dp[4][i][j-1],dp[4][i][j]+a[i][j-1]);}}ll ans=0;for (i=2;i<=n-1;i++) {for (j=2;j<=m-1;j++) {ans=max(ans,dp[1][i-1][j]+dp[4][i+1][j]+dp[2][i][j+1]+dp[3][i][j-1]);ans=max(ans,dp[1][i][j-1]+dp[4][i][j+1]+dp[2][i-1][j]+dp[3][i+1][j]);}}printf("%lld\n",ans);return 0;
}
给你一个数列,问(i-j)^2+(sum[i]-sum[j])^2的最小值。
把每个(i,sum[i])看做平面的一个点,转化为最近点对问题分治进行求解。
#include <cstdio>
#include <iostream>
#include <string.h>
#include <string>
#include <map>
#include <queue>
#include <deque>
#include <vector>
#include <set>
#include <algorithm>
#include <math.h>
#include <cmath>
#include <stack>
#include <iomanip>
#define mem0(a) memset(a,0,sizeof(a))
#define meminf(a) memset(a,0x3f,sizeof(a))
using namespace std;
typedef long long ll;
typedef long double ld;
typedef double db;
const int maxn=100005,inf=0x3f3f3f3f;
const ll llinf=0x3f3f3f3f3f3f3f3f;
const ld pi=acos(-1.0L);
ll a[maxn];
int tem[maxn];struct Point{int x,y;
};
Point p[maxn];bool cmp(Point a,Point b) {return a.x<b.x || (a.x==b.x&&a.y<b.y);
}bool cmpy(int a,int b) {return p[a].y<p[b].y;
}ll sqr(ll x) {return x*x;
}ll dfs(int l,int r) {if (l==r) return llinf;if (l+1==r) return sqr(p[l].x-p[r].x)+sqr(p[l].y-p[r].y);int mid=(l+r)/2;ll d1=dfs(l,mid),d2=dfs(mid+1,r),ans;ans=min(d1,d2);int i,j,m=0;for (i=l;i<=r;i++) if (sqr(p[i].x-p[mid].x)<=ans) tem[m++]=i;sort(tem,tem+m,cmpy);for (i=0;i<m;i++) for (j=i+1;j<m&&sqr(p[tem[i]].y-p[tem[j]].y)<ans;j++)ans=min(ans,sqr(p[tem[i]].x-p[tem[j]].x)+sqr(p[tem[i]].y-p[tem[j]].y));return ans;
}int main() {int n,i;scanf("%d",&n);ll sum=0;for (i=1;i<=n;i++) {scanf("%I64d",&a[i]);sum+=a[i];p[i].x=i;p[i].y=sum;}
// sort(p+1,p+n+1,cmp);ll ans=dfs(1,n);printf("%I64d\n",ans);return 0;
}
E. Points and Segments 欧拉回路,很有趣的一道题。
这篇关于Codeforces Round #245 (Div. 1) ABCDE的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!