一道很好的题,综合很多知识点。

首先复习差分:

     将原来的每个点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,最短路)的更多相关文章

  1. 洛谷 P7718 -「EZEC-10」Equalization(差分转化+状压 dp)

    洛谷题面传送门 一道挺有意思的题,现场切掉还是挺有成就感的. 首先看到区间操作我们可以想到差分转换,将区间操作转化为差分序列上的一个或两个单点操作,具体来说我们设 \(b_i=a_{i+1}-a_i\ ...

  2. 旅游(CSUST省赛选拔赛2+状压dp+最短路)

    题目链接:http://csustacm.com:4803/problem/1016 题目: 思路:状压dp+最短路,比赛的时候有想到状压dp,但是最短路部分写挫了,然后就卡死了,对不起出题人~dis ...

  3. 星空 题意转化,差分,状压DP

    好题(爆搜和puts("2")一个分(雾)),不得不说思维真的强. 首先发现区间翻转很难受,考虑用差分(异或满足可逆性),注意是从0到n+1 然后就转化题意,操作改为选取距离为L的 ...

  4. 星空:差分,状压dp

    总算不再是能用暴力卡常/随机化水过的好T3了. 说是打了两个标签,实际上最关键的是题意转化. 如果你丝毫不转化的话也可以: #include<bits/stdc++.h> using na ...

  5. [CSP-S模拟测试]:邻面合并(状压DP)

    题目背景 $NEWorld$作为一个$3D$游戏,对渲染(图形绘制)的效率要求极高.当玩家扩大视野范围时,可见的方块面数量将会迅速增多,以至于大量的顶点处理很快就成为了图形管线中的瓶颈.乔猫想了想,决 ...

  6. 【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 的状压应该都会吧,状态记录已经 ...

  7. Codeforces 375C - Circling Round Treasures(状压 dp+最短路转移)

    题面传送门 注意到这题中宝藏 \(+\) 炸弹个数最多只有 \(8\) 个,故考虑状压,设 \(dp[x][y][S]\) 表示当前坐标为 \((x,y)\),有且仅有 \(S\) 当中的物品被包围在 ...

  8. BZOJ2595 [Wc2008]游览计划 【状压dp + 最短路】

    题目链接 BZOJ2595 题解 著名的斯坦纳树问题 设\(f[i][j][s]\)表示点\((i,j)\)与景点联通状况为\(s\)的最小志愿者数 设\(val[i][j]\)为\((i,j)\)需 ...

  9. poj 3311 状压dp 最短路

    C - Hie with the Pie Time Limit:2000MS     Memory Limit:65536KB     64bit IO Format:%I64d & %I64 ...

  10. 计蒜客 31436 - 提高水平 - [状压DP]

    题目链接:https://nanti.jisuanke.com/t/31436 作为一名车手,为了提高自身的姿势水平,平时的练习是必不可少的.小 J 每天的训练包含 $N$ 个训练项目,他会按照某个顺 ...

随机推荐

  1. Go语言源码分析之unsafe

    Go语言源码分析之unsafe 1.什么是unsafe unsafe 库让 golang 可以像C语言一样操作计算机内存,但这并不是golang推荐使用的,能不用尽量不用,就像它的名字所表达的一样,它 ...

  2. 开箱即用的Vite-Vue3工程化模板

    开箱即用的Vite-Vue3工程化模板 前言 由于临近毕业肝毕设和论文,停更有一段时间了,不过好在终于肝完了大部分内容,只剩下校对工作 毕设采用技术栈Vue3,Vite,TypeScript,Node ...

  3. Codeforces Round #694 (Div. 2)

     A. Strange Partition 题意:就是求最小和最大的bi/x向上取整的和. 思路:见题解:https://blog.csdn.net/qq_45900709/article/detai ...

  4. select执行顺序

    先from 找到表on过滤 找到两张表有对应关系的记录按join的方式添加外部行where 过滤group by分组having 过滤select 从having 过滤出来的字段中选择需要的字段dis ...

  5. 记一次 .NET 某外贸Web站 内存泄漏分析

    一:背景 1. 讲故事 上周四有位朋友加wx咨询他的程序内存存在一定程度的泄漏,并且无法被GC回收,最终机器内存耗尽,很尴尬. 沟通下来,这位朋友能力还是很不错的,也已经做了初步的dump分析,发现了 ...

  6. Build 2021 :正式发布.NET 6 Preview4

    微软在不断推进.NET 6的可用性,昨晚的Build 2021大会上发布了Preview4, 这是一个很大的版本更新,带来大量的功能,以及接近最终的产品交付质量,不过,这并不意味着可以在生产环境使用了 ...

  7. .Net core Worker Service 扩展库

    .Net core Worker Service 扩展库,目的为更易控制每一个worker 的运行. 提供根据配置文件对每一个Worker的停止.启动和自动解析注册Worker. 获取配置的方式不限于 ...

  8. [bug] IDEA编译时出现 Information:java: javacTask: 源发行版 1.8 需要目标发行版 1.8

    原因 jdk版本选低了 解决 将以下几处jdk版本修改为1.8 Project Structure(File->Project Structure...)>Sources>Langu ...

  9. tar解压某个目录 tar解压某个指定的文件或者文件夹

    tar解压某个目录 tar解压某个指定的文件或者文件夹 发布时间:2017-05-30 来源:服务器之家   1. 先查看压缩文档中有那些文件,如果都不清楚文件内容,然后就直接解压,这个是不可能的 使 ...

  10. && echo suss! || echo failed

    ### && echo suss! || echo failed 加在bash后 ########ls /proc && echo suss! || echo fail ...