地址:https://atcoder.jp/contests/agc033/

D Complexity

dp[ i ][ j ][ k ][ l ] 表示左上角是 ( i , j ) 、右下角是 ( k , l ) 的矩阵的最小代价。

注意到答案是 log(n) + log(m) 级别的,因为每次从中间分, log 次之后就变成一行/列,log(n)+log(m)次就变成 1*1 的格子,代价是 0 。

所以把值和角标互换,dp[ i ][ j1 ][ j2 ][ k ] 表示左上角是 ( i , j1 ) 、右上角是 ( i , j2 ) 、用 k 的代价,往下最长能延伸到哪行。

转移的时候考虑横着切与竖着切。令 d = dp[ i ][ j1 ][ j2 ][ k ] ,首先有 d = dp [ dp[ i ][ j1 ][ j2 ][ k-1 ] ] [ j1 ][ j2 ][ k-1 ] ;

然后考虑 j3 满足 j1 <= j3 < j2 ,使得 [ j1 , j3 ] 和 [ j3+1 , j2 ] 就是分出的两部分;

如果 dp[ i ][ j1 ][ j3 ][ k-1 ] 和 dp[ i ][ j3+1 ][ j2 ][ k-1 ] 有一个是 < d 的,那么说明在这里切之后,两边有一个部分的代价 > k-1 ;

考虑二分找出最大的 min( dp[ i ][ j1 ][ j3 ][ k-1 ] , dp[ i ][ j3+1 ][ j2 ][ k-1 ] ) 。因为固定一条边之后,矩形越大,代价越大,所以根据两个值的大小关系来二分即可。

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int Mx(int a,int b){return a>b?a:b;}
int Mn(int a,int b){return a<b?a:b;}
const int N=;
int n,m,sm[N][N],dp[][N][N][N];
char ch[N][N];
bool chk(int x1,int y1,int x2,int y2)
{
int s=sm[x2][y2]-sm[x2][y1-]-sm[x1-][y2]+sm[x1-][y1-];
return (!s)||s==(x2-x1+)*(y2-y1+);
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=;i<=n;i++)
scanf("%s",ch[i]+);
for(int i=;i<=n;i++)
for(int j=;j<=m;j++)sm[i][j]=sm[i][j-]+(ch[i][j]=='.');
for(int i=;i<=n;i++)
for(int j=;j<=m;j++)sm[i][j]+=sm[i-][j];
for(int i=;i<=n;i++)
for(int j1=;j1<=m;j1++)
for(int j2=j1;j2<=m;j2++)
{
int l=i,r=n,ans=i-;
while(l<=r)
{
int mid=l+r>>;
if(chk(i,j1,mid,j2))ans=mid,l=mid+;
else r=mid-;
}
dp[][i][j1][j2]=ans;
}
if(dp[][][][m]==n){puts("");return ;}
bool u=,v=;
for(int t=;t<=;t++,swap(u,v))
{
for(int i=;i<=n;i++)
for(int j1=;j1<=m;j1++)
for(int j2=j1;j2<=m;j2++)
{
int d=dp[v][dp[v][i][j1][j2]+][j1][j2];
if(dp[v][i][j1][j2]==n)
{ dp[u][i][j1][j2]=n;continue;}
int l=j1,r=j2-;
while(l<=r)
{
int mid=l+r>>;
int t1=dp[v][i][j1][mid],t2=dp[v][i][mid+][j2];
d=Mx(d,Mn(t1,t2));
if(t1>=t2)l=mid+; else r=mid-;
}
dp[u][i][j1][j2]=d;
}
if(dp[u][][][m]==n)
{printf("%d\n",t);return ;}
}
}

E Go around a Circle

题解:https://blog.csdn.net/yzyyylx/article/details/89839025

关键是把 “有一种颜色不能相邻” 和 “长度是奇数” 的限制用 “形如 RRR..RRB 的段” 的角度来看,通过 “ 长度/2 ” 来去掉第二个条件。

注意最后一个连续段如果是和第一个字符相同的字符,不会对长度造成限制。注意是全局的最后一个连续段,而不是该种字符的最后一段。

#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
int Mn(int a,int b){return a<b?a:b;}
const int N=2e5+,mod=1e9+;
int upt(int x){while(x>=mod)x-=mod;while(x<)x+=mod;return x;} int n,m,lm,dp[N],sm[N],ans,g[N];
char s[N];
void solve()
{
g[]=sm[]=;
for(int i=;i<=n;i++)
{
if(i>=)g[i]=sm[i-];
sm[i]=upt(sm[i-]+g[i]);
}
int ans=;//ans=1 for all one color
for(int i=;i<=n;i++)
ans=(ans+(ll)i*g[n-i])%mod;
printf("%d\n",ans);
}
int main()
{
scanf("%d%d",&n,&m);
scanf("%s",s+); bool fg=;
for(int i=;i<=m;i++)
if(s[i]!=s[]){fg=;break;}
if(!fg){solve();return ;}
if(n&){puts("");return ;}
lm=n+;
for(int i=;i<=m;i++)
if(s[i]==s[])//== not !=
{
int j=i;
while(j+<=m&&s[j+]==s[j])j++;
swap(i,j); j=i-j+;
if(i-j==) lm=Mn(lm,j+((j&)==));
else if((j&)&&i!=m)lm=Mn(lm,j);//i!=m not lst
//else if((j&1)&&i!=lst)lm=Mn(lm,j);
}
n>>=; lm=(lm+)>>; dp[]=sm[]=;
for(int i=;i<=n;i++)
{
dp[i]=sm[i-]; if(i>lm)dp[i]=upt(dp[i]-sm[i-lm-]);
sm[i]=upt(sm[i-]+dp[i]);
}
int ans=;
for(int i=;i<=lm;i++)//lm not n
ans=(ans+(ll)i**dp[n-i])%mod;
printf("%d\n",ans);
return ;
}

F Adding Edges

题解代码看了这个:https://atcoder.jp/contests/agc033/submissions/5406519

但还是不太明白这道题是怎么回事……

算法流程大概是:

  考虑把图上的边一条一条加进去,一边加一边让它尽量贴在树上;就是如果有边 ( a, b ) 和 ( a, c ) 且在树上有 a->b->c 的链(a,b,c可以不相邻),就把 ( a, c ) 的边改成 ( b, c ) 的边。

  然后可以认为一个点沿图上的边、顺着树上的链能走到的点都是它可以连边的对象;走不到的就是不能连边的。

  所以主要考虑怎么把第一行的那个操作实现。

  考虑图中加入一条边 ( a, b ) ;把树上 a -> b 的路径找出来; a 和 b 都沿图上的边、顺着树上的链往对方走过去(别走得过了,可以先走 a ,然后 b 走的时候不要超过 a 的位置);

  如果 a 走到路径的另一端,或者 a 和 b 停下之后发现它们在图上已经有边了,就不管了;

  否则就给图连上 ( a, b ) ;然后要考虑这条边是否导致一些边需要修改;需要修改的边一定有一个端点是 a 或者 b ,设一条边 ( a, x ) 要被删掉,需要满足树上有 a->b->x 的链(a,b,x可以不相邻),那么就要把 ( a, x ) 改成 ( b, x ) ;改的操作就是删边,然后递归这个“加边”操作来加入新边。

  把一个点的出边用 set 存就能方便地删边了。

  判断一个点 cr 在两个点 s , t 的路径上,可以通过判断 dis( s, t ) == dis( s, cr ) + dis( cr, t ) 。

  尚不明白正确性或者复杂度……

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<set>
using namespace std;
int rdn()
{
int ret=;bool fx=;char ch=getchar();
while(ch>''||ch<''){if(ch=='-')fx=;ch=getchar();}
while(ch>=''&&ch<='')ret=ret*+ch-'',ch=getchar();
return fx?ret:-ret;
}
const int N=;
int n,m,hd[N],xnt,to[N<<],nxt[N<<],fa[N][N],dis[N][N];
int p[N<<],tot,ans; bool vis[N][N];
set<int> cd[N];
set<int>::iterator it;
void add(int x,int y){to[++xnt]=y;nxt[xnt]=hd[x];hd[x]=xnt;}
void ini_dfs(int cr,int rt,int lj)
{
dis[rt][cr]=lj;
for(int i=hd[cr],v;i;i=nxt[i])
if(!fa[rt][v=to[i]])
{ fa[rt][v]=cr; ini_dfs(v,rt,lj+);}
}
void fnd_path(int x,int y)
{
tot=; p[++tot]=x;
while(x!=y){ x=fa[y][x]; p[++tot]=x;}
}
bool on_path(int cr,int s,int t)
{return dis[s][t]==dis[s][cr]+dis[cr][t];}
void solve(int x,int y)
{
fnd_path(x,y); int s=x,t=y,tmp=;
for(int i=;i<=tot;i++) if(vis[s][p[i]])s=p[i],tmp=i;
for(int i=tot;i>=tmp;i--) if(vis[t][p[i]])t=p[i];//>=tmp
if(s==y||vis[s][t])return;
int tp[N],tt=;//here not use p[]!!!
for(it=cd[s].begin();it!=cd[s].end();it++)
if(on_path(t,(*it),s))tp[++tt]=(*it);
int bj=tt;
for(it=cd[t].begin();it!=cd[t].end();it++)
if(on_path(s,(*it),t))tp[++tt]=(*it);
vis[s][t]=vis[t][s]=;
cd[s].insert(t); cd[t].insert(s);
for(int i=;i<=bj;i++)
{
int v=tp[i]; vis[s][v]=vis[v][s]=;
cd[s].erase(v); cd[v].erase(s);
solve(t,v);
}
for(int i=bj+;i<=tt;i++)
{
int v=tp[i]; vis[t][v]=vis[v][t]=;
cd[t].erase(v); cd[v].erase(t);
solve(s,v);
}
}
void dfs(int cr,int rt)
{
set<int>::iterator it2;//don't use it!!!!!
for(it2=cd[cr].begin();it2!=cd[cr].end();it2++)
if(on_path(cr,rt,(*it2))&&!vis[rt][*it2])
vis[rt][*it2]=,ans++,dfs((*it2),rt);
}
int main()
{
n=rdn();m=rdn();
for(int i=,u,v;i<n;i++)
{ u=rdn();v=rdn();add(u,v);add(v,u);}
for(int i=;i<=n;i++)
fa[i][i]=-,ini_dfs(i,i,);
for(int i=,u,v;i<=m;i++)
{ u=rdn();v=rdn();solve(u,v);}
memset(vis,,sizeof vis);
for(int i=;i<=n;i++) dfs(i,i);
printf("%d\n",ans/);
return ;
}

AGC033 D~F——[ 值放到角标的DP ][ 思路+DP ][ 思路 ]的更多相关文章

  1. Codeforces Round #552 (Div. 3) F. Shovels Shop (前缀和预处理+贪心+dp)

    题目:http://codeforces.com/contest/1154/problem/F 题意:给你n个商品,然后还有m个特价活动,你买满x件就把你当前的x件中最便宜的y件价格免费,问你买k件花 ...

  2. F. Maximum Weight Subset(贪心or树形dp解法)

    题:https://codeforces.com/contest/1249/problem/F 题意:给一颗树,边权为1,节点有点权,问取到一个点集,俩俩之间路径超过k,是点权和最大 思路:贪心地取点 ...

  3. 评估指标:准确率(Precision)、召回率(Recall)以及F值(F-Measure)

    为了能够更好的评价IR系统的性能,IR有一套完整的评价体系,通过评价体系可以了解不同信息系统的优劣,不同检索模型的特点,不同因素对信息检索的影响,从而对信息检索进一步优化. 由于IR的目标是在较短时间 ...

  4. 正确率、召回率和 F 值

    原文:http://peghoty.blog.163.com/blog/static/49346409201302595935709/ 正确率.召回率和 F 值是在鱼龙混杂的环境中,选出目标的重要评价 ...

  5. 选中CheckBoxList的值放到TextBox中,再次选中从textBox中删除

    当选中checkboxlist中的值,直接放到文本框中,在checkboxlist的SelectedIndexChanged事件下执行方法, //将选中的值放到文本框中                ...

  6. apns关于APP数字角标的理解

    前两天群里有兄弟在吐槽,做远程推送的时候:老板要求APP桌面图标的右上角显示红色未读数字(数字角标)要精准,有多少未读通知就显示数字几:但是后台的弟兄在发送推送通知的时候,每次的角标是1,然后要移动端 ...

  7. 查全率(召回率)、精度(准确率)和F值

    文献中的recall rate(查全率或召回率) and precision(精度)是很重要的概念.可惜很多中文网站讲的我都稀里糊涂,只好用google查了个英文的,草翻如下:召回率和精度定义: 从一 ...

  8. 机器学习算法中的准确率(Precision)、召回率(Recall)、F值(F-Measure)

    摘要: 数据挖掘.机器学习和推荐系统中的评测指标—准确率(Precision).召回率(Recall).F值(F-Measure)简介. 引言: 在机器学习.数据挖掘.推荐系统完成建模之后,需要对模型 ...

  9. 推荐系统评测指标—准确率(Precision)、召回率(Recall)、F值(F-Measure)

    下面简单列举几种常用的推荐系统评测指标: 1.准确率与召回率(Precision & Recall) 准确率和召回率是广泛用于信息检索和统计学分类领域的两个度量值,用来评价结果的质量.其中精度 ...

随机推荐

  1. 20150909—Win10系统80端口被System占用

    安装了Windows10系统后,首先是查看80端口是不是被占用, 运行netstat -aon | findstr :80 ,发现pid是4的进程占用着80端口,这还是一个系统进程,kill不掉. 所 ...

  2. 测开之路七十五:linux常用命令

    常用命令: ls:列出文件或目录 pwd:展示当前所在的目录 mkdir:创建目录 mkdir -p :创建连续的目录 cd:切换目录 vi:编辑内容,点i开始编辑,输入::wq保存 cat 显示文件 ...

  3. Maven仓库存在jar包但依旧提示无法下载

    介绍最近服务器的迁移,把原来服务器的地址都更改了,所以私服的地址也改动了,原来项目下载到本地仓库的包,但是重新构建过程中竟然发现依然要提示下载,本地仓库里面明明有包,为什么还要下载? 解决去maven ...

  4. no suitable HttpMessageConverter found for response type

    在使用 RestTemplate 或者 Spring Cloud 的时候,经常会出现这个错误. 基本上出现的场景都是,我们要json,结果来了个 text/html. 两个原因: 第一个就是:服务器返 ...

  5. Excel 技巧

    <!-- Excel跳转到指定行指定列 --> =HYPERLINK("#"&ADDRESS(要跳转到的行数,要跳转到的列数),"跳转")

  6. java绘制带姓的圆

    public class ImageGenerator { private static final Color[] colors = new Color[] { new Color(129, 198 ...

  7. Linux学习笔记之目录配置

    一.目录配置 相关目录说明 /bin              二进制文件 /boot           系统启动文件(内核的初始化文件等) /dev            设备文件(硬盘等) /e ...

  8. USB接口外壳地和信号地间的处理

    USB外壳地和信号地之间串接1M电阻,并且还接一个0.01uf的电容到信号地,能否将一下这样处理的原理和目的: 1.将影响外壳的噪音滤除,不影响信号地: 2.迫使板子上电流是流入内部的信号地,而不是流 ...

  9. IBM IMM默认ID

    默认ID: http://192.168.70.125用户名:USERID密码:PASSW0RD (数字0)

  10. svnkit 异常:Exception in thread "main" org.tmatesoft.svn.core.SVNException: svn: E200030: SQLite error

    https://stackoverflow.com/questions/16063105/org-tmatesoft-sqljet-core-sqljetexception-busy-error-co ...