【模拟8.11】星空(差分转化,状压DP,最短路)
一道很好的题,综合很多知识点。
首先复习差分:
将原来的每个点a[i]转化为b[i]=a[i]^a[i+1],(如果是求和形式就是b[i]=a[i+1]-a[i])
我们发现这样的方便在于我们可以运用前缀和的形式,求出单点值,当然,差分一般支持区间修改
单点查询,同时我们发现异或也满足转化的性质,我们发现异或的区间修改,也可以化为单点修改
然后进行问题转换:在一个序列中按要求修改端点,问最少修改多少次区间全部为0
把原来的每个数转化为差分形式,注意要多加一个b[0]=b[0]^b[1],然后我们发现假设修改
a[1]-a[5]的区间,那么在差分中实际影响的是b[0],b[5]两个值。
同时有一条显然的性质,差分数组中的1是偶数个。
然后再次转化问题:
我们已经知道每种操作的长度(实际在差分数组中长度+1,自己思考)
那么我们可以给数与数连边,连边长度为一,当两个1相遇后,相当于反转,变为0
那么我们将问题转化为图论问题:在n个节点图中,每个节点最多m个边,求出两两最短距离,
然后两个1相遇后全为0,求变为1的最小贡献
然后跑最短路
最后我们发现k的值很小,可以转为状压DP的形式
总的复杂度nmk+(k^2)*(2^k)
- 1 #include<iostream>
- 2 #include<cstdio>
- 3 #include<cstring>
- 4 #include<string>
- 5 #include<map>
- 6 #include<vector>
- 7 #include<set>
- 8 #include<algorithm>
- 9 #include<cmath>
- 10 #include<queue>
- 11 #define MAXN 3000001
- 12 using namespace std;
- 13 int a[MAXN],sum[MAXN];
- 14 int c[MAXN];
- 15 int head[MAXN],tot;
- 16 struct node{int to,n;}e[2700000*2];
- 17 void add(int u,int v)
- 18 {
- 19 e[++tot].to=v;e[tot].n=head[u];head[u]=tot;
- 20 }
- 21 int n,k,m;
- 22 int vis[MAXN];
- 23 int dis[301][301];
- 24 int spfa_dis[MAXN];
- 25 int the_1[MAXN];
- 26 int belong[MAXN];
- 27 void spfa(int root)
- 28 {
- 29 queue<int>q;
- 30 memset(vis,0,sizeof(vis));
- 31 memset(spfa_dis,0x3f3f3f,sizeof(spfa_dis));
- 32 q.push(root);
- 33 spfa_dis[root]=0;
- 34 while(!q.empty())
- 35 {
- 36 int x=q.front();q.pop();vis[x]=0;
- 37 for(int i=head[x];i;i=e[i].n)
- 38 {
- 39 int to=e[i].to;
- 40 if(vis[to])continue;
- 41 if(spfa_dis[to]>spfa_dis[x]+1)
- 42 {
- 43 spfa_dis[to]=spfa_dis[x]+1;
- 44 if(vis[to]==0)
- 45 {
- 46 q.push(to);
- 47 vis[to]=1;
- 48 }
- 49 }
- 50 }
- 51 }
- 52 for(int i=1;i<=the_1[0];++i)
- 53 {
- 54 int ci=the_1[i];
- 55 dis[belong[root]][belong[ci]]=spfa_dis[ci];
- 56 dis[belong[ci]][belong[root]]=spfa_dis[ci];
- 57 //printf("dis[%d][%d]=%d\n",belong[root],belong[ci],spfa_dis[ci]);
- 58 }
- 59 }
- 60 void init()
- 61 {
- 62 for(int i=0;i<=n;++i)//sum[i]=a[i]^a[i+1]
- 63 {
- 64 for(int j=1;j<=m;++j)
- 65 {
- 66 int me=i;
- 67 int l=i-c[j];
- 68 if(l>=0)
- 69 {
- 70 add(i,l);
- 71 //printf("add i=%d l=%d\n",i,l);
- 72 }
- 73 int r=i+c[j];
- 74 if(r<=n)
- 75 {
- 76 add(i,r);
- 77 //printf("add i=%d r=%d\n",i,r);
- 78 }
- 79 }
- 80 }
- 81 for(int i=0;i<=n;++i)
- 82 {
- 83 if(sum[i]==1)
- 84 spfa(i);
- 85 }
- 86 }
- 87 int fir=0,base[30];
- 88 int f[1<<18];
- 89 void DP()
- 90 {
- 91 for(int i=0;i<=n;++i)
- 92 {
- 93 fir|=sum[i]<<i;
- 94 }
- 95 base[0]=1;
- 96 for(int i=1;i<=n;++i)
- 97 {
- 98 base[i]=base[i-1]<<1;
- 99 }
- 100 memset(f,0x3f3f3f,sizeof(f));
- 101 f[base[the_1[0]]-1]=0;
- 102 for(int i=base[the_1[0]]-1;i>=0;--i)
- 103 {
- 104 int ci=i;
- 105 // printf("sr=%d\n",i);
- 106 for(int l=1;l<=the_1[0];++l)
- 107 {
- 108 if(((ci>>(l-1))&1)==1)
- 109 {
- 110 for(int r=l+1;r<=the_1[0];++r)
- 111 {
- 112 if(((ci>>(r-1))&1)==1)
- 113 {
- 114 f[i^base[l-1]^base[r-1]]=min(f[i^base[l-1]^base[r-1]],f[i]+dis[l][r]);
- 115 //printf("state=%d l=%d r=%d %d\n",f[i^base[l-1]^base[r-1]],l,r,dis[l][r]);
- 116 }
- 117 }
- 118 }
- 119 }
- 120 }
- 121 printf("%d\n",f[0]);
- 122 }
- 123 signed main()
- 124 {
- 125 scanf("%d%d%d",&n,&k,&m);
- 126 for(int i=1;i<=k;++i)
- 127 {
- 128 int x;
- 129 scanf("%d",&x);
- 130 a[x]=1;
- 131 }
- 132 for(int i=0;i<=n;++i)
- 133 {
- 134 sum[i]=a[i]^a[i+1];
- 135 if(sum[i]==1)
- 136 {
- 137 the_1[++the_1[0]]=i;
- 138 belong[i]=the_1[0];
- 139 }
- 140 //printf("sum[%d]=%d\n",i,sum[i]);
- 141 }
- 142 for(int i=1;i<=m;++i)
- 143 {
- 144 scanf("%d",&c[i]);
- 145 }
- 146 init();
- 147 DP();
- 148 }
【模拟8.11】星空(差分转化,状压DP,最短路)的更多相关文章
- 洛谷 P7718 -「EZEC-10」Equalization(差分转化+状压 dp)
洛谷题面传送门 一道挺有意思的题,现场切掉还是挺有成就感的. 首先看到区间操作我们可以想到差分转换,将区间操作转化为差分序列上的一个或两个单点操作,具体来说我们设 \(b_i=a_{i+1}-a_i\ ...
- 旅游(CSUST省赛选拔赛2+状压dp+最短路)
题目链接:http://csustacm.com:4803/problem/1016 题目: 思路:状压dp+最短路,比赛的时候有想到状压dp,但是最短路部分写挫了,然后就卡死了,对不起出题人~dis ...
- 星空 题意转化,差分,状压DP
好题(爆搜和puts("2")一个分(雾)),不得不说思维真的强. 首先发现区间翻转很难受,考虑用差分(异或满足可逆性),注意是从0到n+1 然后就转化题意,操作改为选取距离为L的 ...
- 星空:差分,状压dp
总算不再是能用暴力卡常/随机化水过的好T3了. 说是打了两个标签,实际上最关键的是题意转化. 如果你丝毫不转化的话也可以: #include<bits/stdc++.h> using na ...
- [CSP-S模拟测试]:邻面合并(状压DP)
题目背景 $NEWorld$作为一个$3D$游戏,对渲染(图形绘制)的效率要求极高.当玩家扩大视野范围时,可见的方块面数量将会迅速增多,以至于大量的顶点处理很快就成为了图形管线中的瓶颈.乔猫想了想,决 ...
- 【NOI P模拟赛】奶油蛋糕塔(状压 DP)
题面 数据范围 1 ≤ n ≤ 5 × 1 0 5 1\leq n\leq5\times10^5 1≤n≤5×105 . 题解 n ≤ 20 n\leq 20 n≤20 的状压应该都会吧,状态记录已经 ...
- Codeforces 375C - Circling Round Treasures(状压 dp+最短路转移)
题面传送门 注意到这题中宝藏 \(+\) 炸弹个数最多只有 \(8\) 个,故考虑状压,设 \(dp[x][y][S]\) 表示当前坐标为 \((x,y)\),有且仅有 \(S\) 当中的物品被包围在 ...
- BZOJ2595 [Wc2008]游览计划 【状压dp + 最短路】
题目链接 BZOJ2595 题解 著名的斯坦纳树问题 设\(f[i][j][s]\)表示点\((i,j)\)与景点联通状况为\(s\)的最小志愿者数 设\(val[i][j]\)为\((i,j)\)需 ...
- poj 3311 状压dp 最短路
C - Hie with the Pie Time Limit:2000MS Memory Limit:65536KB 64bit IO Format:%I64d & %I64 ...
- 计蒜客 31436 - 提高水平 - [状压DP]
题目链接:https://nanti.jisuanke.com/t/31436 作为一名车手,为了提高自身的姿势水平,平时的练习是必不可少的.小 J 每天的训练包含 $N$ 个训练项目,他会按照某个顺 ...
随机推荐
- Django(6)自定义路由转换器
自定义路径转换器 有时候上面的内置的url转换器并不能满足我们的需求,因此django给我们提供了一个接口可以让我们自己定义自己的url转换器 django内置的路径转换器源码解析 在我们自定义路由转 ...
- 玩转直播系列之RTMP协议和源码解析(2)
一.背景 实时消息传输协议(Real-Time Messaging Protocol)是目前直播的主要协议,是Adobe公司为Flash播放器和服务器之间提供音视频数据传输服务而设计的应用层私有协议. ...
- Java虚拟机栈和PC寄存器
PC Register介绍 JVM中的程序计数寄存器(Program Counter Register)中,Register 的命名源于CPU的寄存器,寄存器存储指令相关的现场信息.CPU只有把数据装 ...
- 啥?SynchronousQueue和钟点房一个道理
今天这篇文章,我们继续讲架构师大刘的故事. 大刘有段时间经常会给一些程序员讲课.这一方面是由于团队培训的需要,一方面也是大刘自身想搞搞凡尔赛,嘚瑟一下自身的实力. 大刘讲课是允许公司任何一个人进去听的 ...
- Envoy:主动健康监测
实验文件 docker-compose version: '3' services: envoy: image: envoyproxy/envoy-alpine:v1.15-latest enviro ...
- markerdown基础
标题 用#+空格 字体 加粗两边两个** 斜体两边* 斜体加粗三个* 引用 '>' 分割线 三个---或者三个*** 图片 ![截图]() 超链接 点击跳转到文章 []+() 列表 1 + 点+ ...
- [bug] Shell:paths must precede expression
参考 https://www.cnblogs.com/peter1994/p/7297656.html
- [设计模式] 设计模式课程(二十)--命令模式(Command)
概述 "行为变化"模式:组件构建过程中,组件行为的变化经常会导致组件本身剧烈的变化."行为变化"模式将组件的行为和组件本身进行解耦,从而支持组件行为的变化,实现 ...
- QT 资源链家暂存
1.Qt右击菜单栏中文化 链接:https://blog.csdn.net/yangxiao_0203/article/details/7488967
- 串口配合DMA接收不定长数据(空闲中断+DMA接收)-(转载)
1.空闲中断和别的接收完成(一个字节)中断,发送完成(发送寄存器控)中断的一样是串口中断: 2.空闲中断是接收到一个数据以后,接收停顿超过一字节时间 认为桢收完,总线空闲中断是在检测到在接收数据后, ...