2017/8/9 离线赛
来源:互联网 发布:北京软件开发平均工资 编辑:程序博客网 时间:2024/05/22 03:26
T1 01完美矩阵
这题考试的时候枚举完两行,找出全1的列,就懵逼了。没有继续往下想,真是可惜了,实际上蛮容易的。枚举上下两行,然后扫每一列,遇到一条全是1的列就塞进数组,遇到上下两行有
int s[M],cnt;int n,m,ans;bool mark[M][M];int sum[M][M];int num[M*M];int u[]={-1,1};void work(int a,int b){ num[0]++; int tmp=0; for(int i=2;i<=cnt;++i){ //(a+1,s[i-1]+1),(b-1,s[i]-1) int t=sum[b-1][s[i]-1]-sum[a][s[i]-1]-sum[b-1][s[i-1]]+sum[a][s[i-1]]; ans+=num[tmp+t-1]+num[tmp+t]+num[tmp+t+1]; tmp+=t;//中间的块 tmp+=b-a-1;//当前列 num[tmp]++; } num[0]--; tmp=0; for(int i=2;i<=cnt;++i){ int t=sum[b-1][s[i]-1]-sum[a][s[i]-1]-sum[b-1][s[i-1]]+sum[a][s[i-1]]; tmp+=t; tmp+=b-a-1; num[tmp]--; }}int main(){ Rd(n);Rd(m); for(int i=1;i<=n;++i) for(int j=1;j<=m;++j){ Rd(mark[i][j]); sum[i][j]=sum[i-1][j-1]+sum[i][j-1]-sum[i-1][j-1]+sum[i-1][j]-sum[i-1][j-1]+u[mark[i][j]]; } for(int i=1;i<=n;++i) for(int j=i+1;j<=n;++j){ for(int k=1;k<=m;++k){ int t=sum[j][k]-sum[i-1][k]-sum[j][k-1]+sum[i-1][k-1]; if(t==j-i+1){ s[++cnt]=k; }else if(!mark[i][k]||!mark[j][k]){ work(i,j); cnt=0; } } if(cnt){ work(i,j); cnt=0; } } Pt(ans); putchar('\n'); return 0;}
T2 codeforces 维修道路
我可以知道,要选择的两条路径的端点一定是树的直径的端点。证明很简单:我们想要的是两条路径的长度的积最大,那就是要两条路径的长度尽可能长,长度尽可能平均,我们知道由树的直径的端点出发(这里指从直径两个端点出发),到其它节点的长度一定比由其它节点出发到达该点的长度长,假如选出的两条路径上不存在有点落在直径上,那它一定不是最优了,因为我们取一条路径的端点与直径端点相连的路径一定比这条路径更长。我们只要把直径抽离出来,求出直径上每个点能拉出来的最长的链,然后求一遍前缀和后缀最大值,最后枚举一个点为分界线即可。
struct edge{ int v,nxt;}e[M<<1];int n;int head[M],edgecnt;int fa[M];void add_edge(int u,int v){ e[++edgecnt].v=v;e[edgecnt].nxt=head[u];head[u]=edgecnt;}int s,id;bool mark[M];void dfs(int x,int t,int d){ fa[x]=t; if(d>s){id=x;s=d;} for(int i=head[x];~i;i=e[i].nxt) if(e[i].v!=t)dfs(e[i].v,x,d+1);}void solve(int x,int d){ mark[x]=1; if(s<d)s=d; for(int i=head[x];~i;i=e[i].nxt) if(!mark[e[i].v])solve(e[i].v,d+1);}int d[M],cnt;int A[M],mxL[M],mxR[M];int main(){ int a,b; memset(head,-1,sizeof(head)); Rd(n); for(int i=1;i<n;i++){ Rd(a);Rd(b); add_edge(a,b); add_edge(b,a); } dfs(1,-1,0); s=0; memset(fa,-1,sizeof(fa)); dfs(id,-1,0); for(int i=id;~i;i=fa[i])d[++cnt]=i; for(int i=1;i<=cnt;i++){ int x=d[i]; mark[x]=1; for(int j=head[x];~j;j=e[j].nxt){ int v=e[j].v; if(mark[v]||v==fa[x])continue; s=0; solve(v,1); if(A[i]<s)A[i]=s; } } for(int i=1;i<=cnt;i++) mxL[i]=max(i-1+A[i],mxL[i-1]); for(int i=cnt;i>=1;i--) mxR[i]=max(cnt-i+A[i],mxR[i+1]); ll ans=0; for(int i=1;i<cnt;i++) ans=max(ans,1LL*mxL[i]*mxR[i+1]); Pt(ans); putchar('\n'); return 0;}
T3 计蒜客 颜值选择
考试的时候我就敲了个
对于这条转移方程,我们如果枚举了
struct P2{ int ans,P; int cost[3][31][61]; int dp[2][61][61]; int L[61],R[61]; void solve(){ for(int i=1;i<=2;i++) for(int j=1;j<=m;j++) for(int x=-k;x<=k;x++) cost[i][j][x+P]=(abs(x+i+j)^U[i][j])*W[i][j]; bool cur=0; for(int i=-k;i<=k;i++) for(int j=-k;j<=k;j++) dp[cur][i+P][j+P]=cost[1][1][i+P]+cost[2][1][j+P]+abs(i+j); for(int i=2;i<=m;i++){ cur=!cur; memset(dp[cur],-1,sizeof(dp[cur])); for(int x=-k;x<=k;x++) for(int a=-k;a<=k;a++){ for(int b=-k;b<=k;b++){ L[-b+P]=dp[!cur][a+P][b+P]+b; R[-b+P]=dp[!cur][a+P][b+P]-b; } for(int b=-k+1;b<=k;b++)L[b+P]=min(L[b+P],L[b-1+P]); for(int b=k-1;b>=-k;b--)R[b+P]=min(R[b+P],R[b+1+P]); for(int y=-k;y<=k;y++) check(dp[cur][x+P][y+P],min(L[y+P]+y,R[y+P]-y)+abs(a+x)+abs(x+y)+cost[1][i][x+P]+cost[2][i][y+P]); } } for(int i=-k;i<=k;i++) for(int j=-k;j<=k;j++) if(~dp[cur][i+P][j+P]) check(ans,dp[cur][i+P][j+P]); Pt(ans); putchar('\n'); } P2(){ans=-1;P=30;memset(dp,-1,sizeof(dp));}}P2;
满分的解法太烦,请看题解。
#include<stdio.h>#include<stdlib.h>#include<string.h>#include<algorithm>#include<iostream>#define For(i,a,b) for(int i=a;i<=b;++i)#define Ror(i,a,b) for(int i=b;i>=a;--i)#define M 888888#define oo 2000000000using namespace std;template <class T>inline void Rd(T &res){ char c;res=0;int k=1; while(c=getchar(),c<48&&c!='-'); if(c=='-'){k=-1;c='0';} do{ res=(res<<3)+(res<<1)+(c^48); }while(c=getchar(),c>=48); res*=k;}template <class T>inline void Pt(T res){ if(res<0){ putchar('-'); res=-res; } if(res>=10)Pt(res/10); putchar(res%10+48);}void check(int &a,int b){ if(a==-1||a>b)a=b;}int n,m,k;int U[20][35],W[20][35];struct P1{ int ans,P; int cost[31][61]; int dp[2][61]; void solve(){ for(int i=1;i<=m;i++) for(int j=-k;j<=k;j++) cost[i][j+P]=(abs(j+1+i)^U[1][i])*W[1][i]; bool cur=0; for(int i=-k;i<=k;i++) dp[cur][i+P]=cost[1][i+P]; for(int i=2;i<=m;i++){ cur=!cur; memset(dp[cur],-1,sizeof(dp[cur])); for(int j=-k;j<=k;j++) if(~dp[!cur][j+P]){ for(int x=-k;x<=k;x++) check(dp[cur][x+P],dp[!cur][j+P]+abs(j+x)+cost[i][x+P]); } } for(int i=-k;i<=k;i++) if(~dp[cur][i+P])check(ans,dp[cur][i+P]); Pt(ans); putchar('\n'); } P1(){ans=-1,P=30;memset(dp,-1,sizeof(dp));}}P1;struct P2{ int ans,P; int cost[3][31][61]; int dp[2][61][61]; int L[61],R[61]; void solve(){ for(int i=1;i<=2;i++) for(int j=1;j<=m;j++) for(int x=-k;x<=k;x++) cost[i][j][x+P]=(abs(x+i+j)^U[i][j])*W[i][j]; bool cur=0; for(int i=-k;i<=k;i++) for(int j=-k;j<=k;j++) dp[cur][i+P][j+P]=cost[1][1][i+P]+cost[2][1][j+P]+abs(i+j); for(int i=2;i<=m;i++){ cur=!cur; memset(dp[cur],-1,sizeof(dp[cur])); for(int x=-k;x<=k;x++) for(int a=-k;a<=k;a++){ for(int b=-k;b<=k;b++){ L[-b+P]=dp[!cur][a+P][b+P]+b; R[-b+P]=dp[!cur][a+P][b+P]-b; } for(int b=-k+1;b<=k;b++)L[b+P]=min(L[b+P],L[b-1+P]); for(int b=k-1;b>=-k;b--)R[b+P]=min(R[b+P],R[b+1+P]); for(int y=-k;y<=k;y++) check(dp[cur][x+P][y+P],min(L[y+P]+y,R[y+P]-y)+abs(a+x)+abs(x+y)+cost[1][i][x+P]+cost[2][i][y+P]); } } for(int i=-k;i<=k;i++) for(int j=-k;j<=k;j++) if(~dp[cur][i+P][j+P]) check(ans,dp[cur][i+P][j+P]); Pt(ans); putchar('\n'); } P2(){ans=-1;P=30;memset(dp,-1,sizeof(dp));}}P2;struct P3{ int S,T,P,tot; int h[M],head[M],edgecnt; int id[20][35][65]; int dep[M],Q[M]; struct edge{ int v,nxt,f; }e[M<<1]; int calc(int x,int y,int z){ return (abs(x+y+z)^U[x][y])*W[x][y]; } void Add(int a,int b,int c){ e[edgecnt]=(edge){b,head[a],c};head[a]=edgecnt++; e[edgecnt]=(edge){a,head[b],0};head[b]=edgecnt++; } void build(){ memset(head,-1,sizeof(head)); edgecnt=0; S=1,T=2,tot=2; For(i,1,n)For(j,1,m){ int p=(i+j)&1; if(p){ For(t,-k,k)id[i][j][t+k+1]=++tot; Add(S,id[i][j][1],(abs(-k+i+j)^U[i][j])*W[i][j]); for(int t=-k+1;t<k;t++) Add(id[i][j][t+k],id[i][j][t+k+1],(abs(t+i+j)^U[i][j])*W[i][j]); Add(id[i][j][k+k],T,(abs(k+i+j)^U[i][j])*W[i][j]); }else{ Ror(t,-k,k)id[i][j][k-t+1]=++tot; Add(S,id[i][j][1],(abs(k+i+j)^U[i][j])*W[i][j]); for(int t=k-1;t>-k;t--) Add(id[i][j][k-t],id[i][j][k-t+1],(abs(t+i+j)^U[i][j])*W[i][j]); Add(id[i][j][k+k],T,(abs(-k+i+j)^U[i][j])*W[i][j]); } For(t,1,2*k){ if(i>1){ Add(id[i-1][j][t],id[i][j][t],1); Add(id[i][j][t],id[i-1][j][t],1); } if(j>1){ Add(id[i][j-1][t],id[i][j][t],1); Add(id[i][j][t],id[i][j-1][t],1); } } } } bool BFS(){ memset(dep,0,sizeof(dep)); int L=0,R=0; dep[S]=1; Q[R++]=S; while(L<R){ int now=Q[L++]; for(int i=head[now];~i;i=e[i].nxt){ int v=e[i].v; if(e[i].f&&!dep[v]){ dep[v]=dep[now]+1; Q[R++]=v; } } } return dep[T]; } int dfs(int x,int t,int f){ if(x==t)return f; for(int &i=h[x];~i;i=e[i].nxt){ int v=e[i].v; if(dep[v]==dep[x]+1&&e[i].f){ int d=dfs(v,t,min(e[i].f,f)); if(d){ e[i].f-=d; e[i^1].f+=d; return d; } } } return 0; } int Dinic(){ int ans=0,f; while(BFS()){ for(int i=0;i<=tot;i++)h[i]=head[i]; while(f=dfs(S,T,2e9))ans+=f; } return ans; } void solve(){ build();// for(int i=0;i<=0;i++)// for(int j=head[i];~j;j=e[j].nxt){// cout<<i<<" "<<e[j].v<<" "<<e[j].f<<endl;// } Pt(Dinic()); putchar('\n'); } P3(){P=30;}}P3;int main(){ int size = 32 << 20; // 32MB char *p = (char*)malloc(size) + size; __asm__("movl %0, %%esp\n" :: "r"(p)); Rd(n);Rd(m);Rd(k); for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) Rd(U[i][j]); for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) Rd(W[i][j]);// if(n==1)P1.solve();// else if(n==2)P2.solve(); P3.solve(); return 0;}
- 2017/8/9 离线赛
- 2017/9/2 离线赛
- 2017/9/15 离线赛
- 2017/8/5 离线赛
- 2017/8/7 离线赛
- 2017/8/11 离线赛
- 2017/8/14 离线赛
- 2017/8/19 离线赛
- 2017/8/20 离线赛
- 2017/8/26 离线赛
- 2017-9-24离线赛总结
- 2017-9-25离线赛总结
- 2017-9-26离线赛总结
- 2017-9-28离线赛总结
- 2017-9-29离线赛总结
- 2017-10-9离线赛总结
- 2017-11-9离线赛总结
- 2017-10-8离线赛总结
- 179. Largest Number
- 萌新开始学安卓啦
- 悲观锁
- 使用ffmpeg合并视频文件的三种方法
- hive查询与优化
- 2017/8/9 离线赛
- 机器学习算法总结--随机森林
- react native Text实现限制行数不显示省略号,尾部直接截断
- JAVA常用日期比较操作说明
- 说一说排序算法,稳定性,复杂度
- vue
- 数字签名与数字证书技术简介(一)
- Scala 之 模式匹配
- 常用Markdown(MD)语法