【无码专区9】序列统计(带权并查集 + 前缀和建边 + dp)

因为只有std,没有自我实现,所以是无码专区

主要是为了训练思维能力

solution才是dls正解,但是因为只有潦草几句,所以大部分会有我自己基于正解上面的算法实现过程,可能选择的算法跟std中dls的实现不太一样。

std可能也会带有博主自己的注释。


problem

nnn 个整数,第 iii 个整数在 [xi,yi][x_i,y_i][xi,yi] 区间。

给定 mmm 个限制,形如 li,ri,sil_i,r_i,s_ili,ri,si ,要求第 lil_ilirir_iri 的数字加起来对 222 取模余数为 sis_isi

求有多少种整数序列满足上面限制,答案对 109+710^9+7109+7 取模。

以及输出字典序最小的整数序列。

n≤40,m≤100,0≤xi≤yi≤1e9n\le 40,m\le 100,0\le x_i\le y_i\le 1e9n40,m100,0xiyi1e9

1s,128MB1s,128MB1s,128MB


my idea

因为限制是在模 222 意义下的,所以真的有关系的只是这个数是奇数还是偶数。

对于 50%50\%50% 的数据点 n≤20n\le 20n20,直接 2n2^n2n 枚举每一位是选的奇数还是偶数,然后枚举所有限制判断是否合法,顺道可以记录一下字典序最小解及个数,时间复杂度 O(2nm)O(2^nm)O(2nm)

[li,ri][l_i,r_i][li,ri] 的限制转化为前缀和做差的限制,即 sum(r)−sum(l−1)sum(r)-sum(l-1)sum(r)sum(l1)

sum(i)sum(i)sum(i) 看作一个点,将一个限制看作 li−1→ril_i-1\rightarrow r_ili1ri 的有向边,边权为 sis_isi

这样会形成若干个相互独立的有向图。

考虑将这些图,以及图内一个点可能引发的若干条边合并起来,变成一条链。

i.e. 要求 [3,5]=1,[4,8]=0,[4,7]=1⇒2→5(1),3→8(0),3→7(1)[3,5]=1,[4,8]=0,[4,7]=1\Rightarrow 2\rightarrow 5(1),3\rightarrow 8(0),3\rightarrow 7(1)[3,5]=1,[4,8]=0,[4,7]=125(1),38(0),37(1)

⇒2→3(x)→5(x⨁1)→7(x⨁1)→8(x)\Rightarrow 2\rightarrow 3(x)\rightarrow 5(x\bigoplus 1)\rightarrow 7(x\bigoplus1)\rightarrow 8(x)23(x)5(x1)7(x1)8(x)

当最开始的一条边上的权确定时,整条链就确定了。

具体而言:直接枚举两两限制进行合并,[l1,r1][l2,r2],l1<l2<r1<r2⇒l1→l2→r1→r2[l_1,r_1][l_2,r_2],l_1<l_2<r_1<r_2\Rightarrow l_1\rightarrow l_2\rightarrow r_1\rightarrow r_2[l1,r1][l2,r2],l1<l2<r1<r2l1l2r1r2

然后对于每个参与点进行限制的 dfsdfsdfs,开始跑每条边的边权。

如果到相同点的边权在取模 222 意义下不同,说明限制之间出现矛盾。

注意到并不是每个数都在这条链上,i.e. 4,6,1...4,6,1...4,6,1...

这些边只是起将限制紧密联系在一起的作用。

每两个点之间的原区间的方案数是可以通过 dpdpdp 计算的。

dpi,0/1:dp_{i,0/1}:dpi,0/1:iii 个数和为 0/10/10/1 (在(mod2)\pmod 2(mod2) 的意义下)的方案数。

一个数的取值区间 [li,ri][l_i,r_i][li,ri],无非可以划分为奇数 xxx 个,偶数 yyy 个。

选奇数会改变奇偶,选偶数则不改变。
dpi,0←dpi−1,0×y+dpi−1,1×xdpi,1←dpi−1,0×x+dpi−1,1×ydp_{i,0}\leftarrow dp_{i-1,0}\times y+dp_{i-1,1}\times x\\dp_{i,1}\leftarrow dp_{i-1,0}\times x+dp_{i-1,1}\times y dpi,0dpi1,0×y+dpi1,1×xdpi,1dpi1,0×x+dpi1,1×y
没有限制的区间就这么转移,一旦有类似与上面的边限制,去除掉不合法,继续转移即可。

貌似这样转移很困难w(゚Д゚)w


solution

首先, 考虑前缀和, 每个 [l,r][l,r][l,r] 的限制转化为 l−1l-1l1rrr 两个前缀和之间的限制。

然后对所有限制进行连边。

每个连通块的奇偶性只有两种选择方法。【并不需要像我那么傻逼地去缩成一条链】

我们可以枚举每个连通块的奇偶性, 然后统计答案。

注意到, 如果一个连通块只有 111 个数,我们不需要枚举(放到后面去 dpdpdp

因为这个位置的奇偶性不会影响到别的元素。

所以只要在枚举完每个大于等于 222 的连通块的奇偶性之后, 从右往左做一遍 dpdpdp, 记录一下当前前缀和的奇偶性是多少, 对应的方案数即可。

时间复杂度 O(2n2n)O(2^\frac{n}{2}n)O(22nn)


std

#include <bits/stdc++.h>
using namespace std ;typedef long long LL ;#define clr( a , x ) memset ( a , x , sizeof a )const int MAXN = 42 ;
const int mod = 1e9 + 7 ;char buf[1000000] ;
int len ;
int p[MAXN], c[MAXN] ;
int L[MAXN], R[MAXN], odd[MAXN], even[MAXN] ;
int dp[MAXN][MAXN][2] ;
pair < int, int > nxt[MAXN][MAXN][2] ;
int ans[MAXN], tmp[MAXN] ;
int rt[MAXN], col[MAXN] ;
int idx[MAXN] ;
int use[MAXN] ;
int n, m ;
int T ;int F ( int x ) { //带权并查集实现前缀和限制if ( p[x] == x ) return x ;int res = F ( p[x] ) ;c[x] ^= c[p[x]] ;return p[x] = res;
}int upd ( int x, int y, int o, int n ) {if ( dp[y][x][o] == 0 )return 0 ;int m = y - x ;for ( int i = x ; i <= y ; ++ i ) {tmp[i] = nxt[y][i][o].first ;o = nxt[y][i][o].second ;}return 1 ;
}void up ( int ok ) {if ( !ok )return ;for ( int i = 1 ; i <= n ; ++ i ) {if ( tmp[i] > ans[i] )return ;if ( tmp[i] < ans[i] ) {for ( int j = 1 ; j <= n ; ++ j ) {ans[j] = tmp[j] ;}return ;}}
}void add ( int x ) {if ( x / 10 )add ( x / 10 ) ;buf[len ++] = x % 10 + '0' ;
}int main() {freopen("parity.in", "r", stdin);freopen("parity.out", "w", stdout);scanf ( "%d%d", &n, &m ) ;for ( int i = 0 ; i <= n ; ++ i ) {p[i] = i ;c[i] = 0 ;use[i] = 0 ;}for ( int i = 1 ; i <= n ; ++ i ) {scanf ( "%d%d", &L[i], &R[i] ) ;int tmp = R[i] - L[i] + 1 ; //计算i可选范围内奇数和偶数的个数odd[i] = tmp / 2 + ( tmp % 2 == 1 && R[i] % 2 == 1 ) ;even[i] = tmp / 2 + ( tmp % 2 == 1 && R[i] % 2 == 0 ) ;}for ( int i = 1 ; i <= n ; ++ i ) {for ( int j = 1 ; j <= n + 1 ; ++ j ) {dp[i][j][0] = dp[i][j][1] = 0 ;nxt[i][j][0] = make_pair ( mod, mod ) ;nxt[i][j][1] = make_pair ( mod, mod ) ;}}//dp[l][r][0/1]:计算[l,r]区间内数的奇偶性for ( int i = 1 ; i <= n ; ++ i ) {dp[i][i + 1][0] = 1 ;for ( int j = i ; j >= 1 ; -- j ) {dp[i][j][0] = ( 1LL * dp[i][j + 1][1] * odd[j] + 1LL * dp[i][j + 1][0] * even[j] ) % mod ;dp[i][j][1] = ( 1LL * dp[i][j + 1][0] * odd[j] + 1LL * dp[i][j + 1][1] * even[j] ) % mod ;}for ( int j = 1 ; j <= i ; ++ j ) {if ( dp[i][j + 1][1] && odd[j] ) {nxt[i][j][0] = min ( nxt[i][j][0], make_pair ( L[j] + ( L[j] % 2 == 0 ), 1 ) ) ;}if ( dp[i][j + 1][0] && even[j] ) {nxt[i][j][0] = min ( nxt[i][j][0], make_pair ( L[j] + ( L[j] % 2 == 1 ), 0 ) ) ;}if ( dp[i][j + 1][0] && odd[j] ) {nxt[i][j][1] = min ( nxt[i][j][1], make_pair ( L[j] + ( L[j] % 2 == 0 ), 0 ) ) ;}if ( dp[i][j + 1][1] && even[j] ) {nxt[i][j][1] = min ( nxt[i][j][1], make_pair ( L[j] + ( L[j] % 2 == 1 ), 1 ) ) ;}}}int ok = 1 ;for ( int i = 1 ; i <= m ; ++ i ) {int u, v, w, x, y ;scanf ( "%d%d%d", &u, &v, &w ) ;-- u ;x = F ( u ) ;y = F ( v ) ;use[u] = use[v] = 1 ;if ( x != y ) {if ( x < y ) swap ( x, y ) ;p[x] = y ;c[x] = ( c[u] - c[v] + 2 + w ) % 2 ;} else if ( ( c[u] ^ c[v] ) != w ) ok = 0 ;}if ( !ok ) { //限制冲突 无解-1buf[len ++] = '0' ;buf[len ++] = '\n' ;buf[len ++] = '-' ;buf[len ++] = '1' ;buf[len ++] = '\n' ;return 0;}int cnt = 0, tot = 0, uns = 0;for ( int i = 0 ; i <= n ; ++ i )if ( use[i] ) {if ( F ( i )  == i )rt[cnt ++] = i;idx[tot ++] = i;} elseuns++;int res = 0, OK = 0 ;for ( int i = 1 ; i <= n ; ++ i )ans[i] = mod ;for ( int s = 0 ; s < 1 << cnt ; ++ s ) {if ( cnt && rt[0] == 0 && s % 2 )continue ;col[0] = 0 ;for ( int i = 0 ; i < cnt ; ++ i ) {col[rt[i]] = s >> i & 1 ;}int ans = 1, j = 0, ok = 1 ;for ( int o = ( rt[0] == 0 ) ; o < tot ; ++ o ) {int i = idx[o], x = p[i] ;if ( x != i )col[i] = col[x] ^ c[x] ^ c[i] ;ans = 1LL * ans * dp[i][j + 1][col[j] ^ col[i]] % mod ;ok &= upd ( j + 1, i, col[j] ^ col[i], j ) ;if ( !ok )break ;j = i ;}if ( ok && j < n ) {ans = 1LL * ans * ( dp[n][j + 1][0] + dp[n][j + 1][1] ) % mod ;int a = upd ( j + 1, n, 0, j ) ;up ( ok && a ) ;int b = upd ( j + 1, n, 1, j ) ;up ( ok && b ) ;ok &= a | b ;} elseup ( ok ) ;if ( ok )OK = 1 ;res = ( res + ans ) % mod ;}if ( !OK ) {buf[len ++] = '0' ;buf[len ++] = '\n' ;buf[len ++] = '-' ;buf[len ++] = '1' ;buf[len ++] = '\n' ;} else {add ( res ) ;buf[len ++] = '\n' ;for ( int i = 1 ; i <= n ; ++ i ) {add ( ans[i] ) ;buf[len ++] = i < n ? ' ' : '\n' ;}}buf[len] = 0;printf("%s", buf);
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/316747.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Acwing 217. 绿豆蛙的归宿

Acwing 217. 绿豆蛙的归宿 题意&#xff1a; 给出一个有向无环的连通图&#xff0c;起点为 1&#xff0c;终点为 N&#xff0c;每条边都有一个长度。 数据保证从起点出发能够到达图中所有的点&#xff0c;图中所有的点也都能够到达终点。 绿豆蛙从起点出发&#xff0c;走向…

LNOI2022:游记

前言 The world is cruel. 真的为身边的一些人感到可惜… Day -1 PKUSC刚刚考完&#xff0c;然后就要省选了&#xff1f; 板子实在是看的够够的了。 然而还是不想深度做题&#xff0c;看了看APIO的practise&#xff0c;T1写完发现偶数还得特别做&#xff0c;就感觉很麻烦&…

合肥.NET技术社区首次线下聚会全程回顾【多图】

2019年3月16日对于合肥.NET来说是一个特别的日子&#xff0c;因为这是合肥.NET技术社区首次非正式线下聚会&#xff01;这次聚会受场地限制&#xff08;毕竟是聚餐的形式&#xff09;&#xff0c;即使换成了小椅子后&#xff0c;最多也只能容纳24个人&#xff0c;所以还有一些小…

【无码专区10】第K大查询(双向链表 /主席树+st表)

已自我实现&#xff0c;但还是归入无码专区序列。哈哈哈哈哈 对于my idea部分&#xff0c;我的每一个想法都实现了&#xff0c;可供参考。 problem 给定一个 1∼n1\sim n1∼n 的排列和 kkk&#xff0c;求所有 r−l1≥kr-l1\ge kr−l1≥k 的区间 [l,r][l,r][l,r] 中的第 kkk 大…

SignalR第一节-在5分钟内完成通信连接和消息发送

前言首先声明&#xff0c;这又是一个小白从入门到进阶系列。 SignalR 这个项目我关注了很长时间&#xff0c;中间好像还看到过微软即将放弃该项目的消息&#xff0c;然后我也就没有持续关注了&#xff0c;目前的我项目中使用的是自己搭建的 WebSocket &#xff0c;连接管理和消…

P5327 [ZJOI2019]语言(线段树合并、生成树)

解析 只会扫描线树剖的三只log&#xff08;悲 考虑对每个 uuu 考虑合法的 vvv 的集合&#xff0c;必然是一个联通块。 进一步的&#xff0c;观察到这个联通块就是由所有经过 uuu 的路径的端点形成的最小生成树。 我们有一个最小生成树的经典结论&#xff1a;最小生成树边权和…

【学习笔记】信息学竞赛中的概率与期望小结

信息竞赛——概率与期望事件事件的蕴含、包含事件的互斥事件的对立事件的和&#xff08;并&#xff09;事件的积&#xff08;交&#xff09;事件的差概率事件的独立性全概率公式贝叶斯公式概率DP&#xff08;竞赛中的考察&#xff09;期望&#xff08;竞赛中的考察&#xff09;…

Acwing 218. 扑克牌

Acwing 218. 扑克牌 题意&#xff1a; 一副扑克牌(54张)&#xff0c;问得到A 张黑桃、B 张红桃、C 张梅花、D 张方块需要翻开的牌的张数的期望值 E 是多少&#xff1f; 如果翻开的牌是大王或者小王&#xff0c;Admin 将会把它作为某种花色的牌放入对应堆中&#xff0c;使得放…

尝试:Script Lab,快速 O365 开发工具//SL01)

《前言》Script Lab 我希望有一个系列&#xff08;连载&#xff09;&#xff0c;可是我挺担心没偿没有能力去驾驭它。虽然早年前己经接触过&#xff0c;但一直未有下决心开始 Office 365 的开发之旅&#xff0c;虽然一直被光标老师所鼓舞&#xff0c;但是我心有旁骛还没有真正做…

P3710 方方方的数据结构(kd-tree)

解析 写吐了… 一开始觉得线段树分治直接做就行简直是个伞兵题&#xff0c;写完挂掉才想起来线段树分治会打乱操作顺序导致全假… 重构吧&#xff01; 炸裂之下去贺题解&#xff0c;std做法 O(mmlog⁡m)O(m\sqrt m\log m)O(mm​logm) 令人谔谔&#xff0c;但kd-tree做法确实挺…

[POJ 3709] K-Anonymous Sequence(斜率优化dp / 动态维护凸包)

K-Anonymous Sequence看了两年前自己的博客&#xff0c;真的好青涩&#xff0c;连 markdown 都不太会用。 确实观赏感不是很好。 学习真的是慢慢积累的过程&#xff0c;以前感觉理解很困难的事&#xff0c;随着知识的增长&#xff0c;现在都基本悟了。 problem POJ3709 so…

Keiichi Tsuchiya the Drift King

Keiichi Tsuchiya the Drift King 题意&#xff1a; 给定一辆小车长宽分别为 b&#xff0c;a&#xff0c;轨道的圆弧部分半径为 r&#xff0c;圆弧对应的角度为 d&#xff0c;求出小车能通过轨道的最小轨道宽度 w。 题解&#xff1a; 我们考虑小车处于什么状态会使弯道最宽…

AspNet Core 下利用普罗米修斯+Grafana构建Metrics和服务器性能的监控

概述Prometheus是一套开源的监控&报警&时间序列数据库的组合,起始是由SoundCloud公司开发的。该项目有非常活跃的社区和开发人员&#xff0c;目前是独立的开源项目&#xff0c;现在最常见的Kubernetes容器管理系统中&#xff0c;通常也会搭配Prometheus进行监控。prome…

模板:pb_ds指南

科技改变生活 前言 本来一直被畏于巨长的声明&#xff0c;没有学这个东西… 直到 棘手的操作 这道题&#xff0c;pb_ds模拟实现的两个log的做法不仅好写的一批&#xff0c;连时间竟然也把我单log的左偏树爆踩了&#xff1f;&#xff1f;&#xff1f; … 我选择打不过就加入… …

【学习笔记】多重背包相关优化——二进制优化/单调队列优化

多重背包——二进制优化/单调队列优化二进制优化单调队列优化代码都是 POJ1742 的&#xff0c;注意&#xff0c;那道题二进制优化会超时。 普通的多重背包式子&#xff0c;物品个数限制&#xff1a;c[i]c[i]c[i]&#xff0c;单个物品价值 w[i]w[i]w[i]&#xff0c;每个物品的体…

Game of Swapping Numbers

Game of Swapping Numbers 题意&#xff1a; A&#xff0c;B两个数组&#xff0c;让你对A进行k次操作&#xff0c;每次操作为选两个位置的数&#xff0c;进行交换&#xff0c;求最大化的Σ|Ai-Bi| 题解&#xff1a; 以前有做过最小化的情况&#xff0c;就是把每次交换作定量…

软件工程真的是一门什么用都没有的学科么?

软件工程真的是一门什么用都没有的学科么&#xff1f;-----读《构建之法》有感楔子我很惭愧&#xff0c;构建之法这本书已经出版四五年了&#xff0c;我之前却未曾涉猎&#xff0c;还是在通过组织长沙.net技术社区之后&#xff0c;才因为因缘际遇有幸认识邹欣邹老师之后&#x…

Ball Dropping

Ball Dropping 题意&#xff1a; 求&#xff1f;的具体长度 题解&#xff1a; 算一算就出来了 代码&#xff1a; #include<bits/stdc.h> using namespace std; int main(){double r,a,b,h;cin>>r>>a>>b>>h;if(2*r<b&&2*r<…

[WF2011] MachineWorks(李超树优化dp)

[WF2011]MachineWorksproblem BZOJ3963 solution 来得比较快的是&#xff0c;直接设 dpi,j:dp_{i,j}:dpi,j​: 考虑第 jjj 天换购 iii 机器。 但是马上注意到天数是 1e91e91e9 级别的&#xff0c;而机器是 1e51e51e5 级别。 稍微想想&#xff0c;就能知道&#xff0c;因为…

P3644 [APIO2015]八邻旁之桥(中位数、堆)

前言 卡了很长时间的一个题。 一开始 k1 的关键性质把握就跑偏了&#xff0c;后面基本在硬做… 关键就是一直把每个人当成一条线段作为整体在看&#xff0c;使问题很复杂… 最后用 three-pointers 磕磕绊绊搞出来了。 但是根本不用&#xff01; 解析 这题关键就在于&#xf…