博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
星空:差分,状压dp
阅读量:4606 次
发布时间:2019-06-09

本文共 2440 字,大约阅读时间需要 8 分钟。

总算不再是能用暴力卡常/随机化水过的好T3了。

说是打了两个标签,实际上最关键的是题意转化。

如果你丝毫不转化的话也可以:

1 #include
2 using namespace std; 3 int dp[2][1048577],b[65],k,n,m,x[9],f=1,mx; 4 int main(){ 5 scanf("%d%d%d",&n,&k,&m); 6 for(int i=1;i<=k;++i)scanf("%d",&x[i]); 7 for(int i=1;i<=m;++i)scanf("%d",&b[i]),mx=max(mx,b[i]); 8 if(mx<=16){ 9 memset(dp,0x3f,sizeof dp);dp[0][0]=0;const int maxst=(1<
=b[j])for(int st=0;st<=maxst;++st)13 dp[i&1][st<<1^((1<
<<1^((1<
考场上56分,直接状压最大的操作区间,再加骗分

(本来想上去讲讲的毕竟勉强算是个单题最高分但其实很水)

然而自然骗分并不稳定。考后再测:

考场上rp生效了!

这个暴力可以稍微讲一讲:

我们先观察数据范围可以发现k超级小但那是全部测试点是正解的事与我无瓜并不会用

其次m也不大但理由同上。

但是那个bi在某些测试点里小,也有些特别大。

和《奇怪的道路》有点莫名其妙的像?状压它!

只不过是把单点的操作换成了区间,其余真的没有什么区别。

时间复杂度O(nm2max(bi))。我不像题解一样只压了4而是尝试压了一下16。T了不要想了。

考场上还剩那么几分钟,干啥?骗分啊!

答案小于4。挺好。只有0123。

0好说啊,所有灯都亮着就是0啊。

1也好说啊,没亮的灯连成一片了而且操作里有能刚好这么长的就是1啊。

2得搜索吧,懒得打。rand一下。

效果不错。

好了好了废话太多说正解。

首先我们的操作是一次一个区间,暴力扫肯定T。区间异或怎么搞?

其实异或运算和加法在很多方面上有互通之处,如果是加法,你会怎么做?

差分啊!然后你就可以惊奇地发现异或的确也可以差分。

那么刚开始对于一个全亮的串,几个不亮的灯就是单点异或。也放进差分数组里处理。

每一个操作就是对于l~r区间异或。其实就是对于相隔距离一定的两个点同时异或一下。

我们的最终目标是得到一个全0串,差分数组全0就表示原区间全0,也就是灯都亮了。

我们继续考虑每一步操作,每次异或两个位置,如果它们都是0你异或完就都是1,和要消除1的目标不符且并不会i作出正贡献。

所以你只会同时选两个1或一个1一个0。前者会使两个1都消失。后者会让两者交换位置。

那么既然你想让它们都消失,就是不断改变1的位置最后让它们两两撞在一起消失掉。

而它每次会移动多少,就是向左右移动它给定的bi位啊。

跑bfs,找出所有1的单源最短路。(不建议打dijkstra或SPFA,常数大,而且就是说明你不理解这个bfs)

因为这个bfs每次走都是一次操作,相当于边权是1,队列里自带单调递增。

不要把边建出来,某牛T了。

然后我们就找出了每一对数字1对撞需要几次操作。

接下来状压它,不断枚举你要让哪两个1对消更新状态即可。

1 #include
2 using namespace std; 3 int n,m,k,b[65],x[17],y[9],cnt,dt[40005],cost[17][17],q[40005],t,dp[1048577]; 4 int main(){y[0]=-1; 5 scanf("%d%d%d",&n,&k,&m); 6 for(int i=1;i<=k;++i)scanf("%d",&y[i]); 7 for(int i=1;i<=m;++i)scanf("%d",&b[i]); 8 for(int i=1;i<=k;++i){ 9 if(y[i]+1!=y[i+1])x[++cnt]=y[i];10 if(y[i]-1!=y[i-1])x[++cnt]=y[i]-1;11 }12 memset(cost,0x3f,sizeof cost);13 for(int i=1;i<=cnt;++i){14 memset(dt,0x3f,sizeof dt);dt[q[t=1]=x[i]]=0;15 for(int h=1;h<=t;++h)for(int j=1;j<=m;++j){16 if(q[h]+b[j]<=n&&dt[q[h]+b[j]]==0x3f3f3f3f)dt[q[++t]=q[h]+b[j]]=dt[q[h]]+1;17 if(q[h]-b[j]>=0&&dt[q[h]-b[j]]==0x3f3f3f3f)dt[q[++t]=q[h]-b[j]]=dt[q[h]]+1; 18 }19 for(int j=i+1;j<=cnt;++j)cost[i][j]=cost[j][i]=dt[x[j]];20 }21 memset(dp,0x3f,sizeof dp);dp[0]=0;22 for(int s=0;s<1<
没上Kb。1008B

转载于:https://www.cnblogs.com/hzoi-DeepinC/p/11335411.html

你可能感兴趣的文章
模版include的用法
查看>>
LotusScript_导出数据库路径和名称
查看>>
String ,StringBuffer 与S tringBuilder的区别??
查看>>
PgSQL · 追根究底 · WAL日志空间的意外增长
查看>>
struts2笔记之struts:property标签
查看>>
Threejs.教程
查看>>
超闩锁和子闩锁如何工作的
查看>>
ZendStudio快捷键
查看>>
[ovs] ovs开启日志debug
查看>>
Eclipse插件项目中读取文件
查看>>
jquery定义链接跳转的高亮显示
查看>>
CheckListBox怎样得到多选值?
查看>>
2370 小机房的树
查看>>
三道题(关于虚表指针位置/合成64位ID/利用栈实现四则运算)
查看>>
Vijos P1243 生产产品 (单调队列优化DP)
查看>>
mysql 数据表操作 目录
查看>>
iOS常用第三方库 -转
查看>>
Android布局学习
查看>>
实时通讯与非实时通讯
查看>>
jQuery中事件绑定与解绑
查看>>