在统计计算中,最大期望(EM)算法是在概率(probabilistic)模型中寻找参数最大似然估计的算法,其中概率模型依赖于无法观测的隐藏变量(Latent Variable)。最大期望经常用在机器学习和计算机视觉的数据聚类(Data Clustering) 领域。最大期望算法经过两个步骤交替进行计算,第一步是计算期望(E),利用对隐藏变量的现有估计值,计算其最大似然估计值;第二步是最大化(M),最大 化在 E 步上求得的最大似然值来计算参数的值。M 步上找到的参数估计值被用于下一个 E 步计算中,这个过程不断交替进行。

最大期望值算法由 Arthur Dempster,Nan LairdDonald Rubin在他们1977年发表的经典论文中提出。他们指出此方法之前其实已经被很多作者"在他们特定的研究领域中多次提出过"。

我们用  表示能够观察到的不完整的变量值,用  表示无法观察到的变量值,这样  和  一起组成了完整的数据。 可能是实际测量丢失的数据,也可能是能够简化问题的隐藏变量,如果它的值能够知道的话。例如,在混合模型(Mixture Model)中,如果“产生”样本的混合元素成分已知的话最大似然公式将变得更加便利(参见下面的例子)。

估计无法观测的数据

让  代表矢量 θ:  定义的参数的全部数据的概率分布(连续情况下)或者概率聚类函数(离散情况下),那么从这个函数就可以得到全部数据的最大似然值,另外,在给定的观察到的数据条件下未知数据的条件分布可以表示为:

EM算法有这么两个步骤E和M:

Expectation step: Choose q to maximize F:
Maximization step: Choose θ to maximize F:
举个例子吧:高斯混合

假设 x = (x1,x2,…,xn) 是一个独立的观测样本,来自两个多元d维正态分布的混合, 让z=(z1,z2,…,zn)是潜在变量,确定其中的组成部分,是观测的来源.

即:

 and 

where

 and 

目标呢就是估计下面这些参数了,包括混合的参数以及高斯的均值很方差:

似然函数:

where  是一个指示函数 ,f 是 一个多元正态分布的概率密度函数. 可以写成指数形式:

下面就进入两个大步骤了:
E-step

给定目前的参数估计 θ(t),  Zi 的条件概率分布是由贝叶斯理论得出,高斯之间用参数 τ加权:

.

因此,E步骤的结果:

M步骤

Q(θ|θ(t))的二次型表示可以使得 最大化θ相对简单.  τ, (μ1,Σ1) and (μ2,Σ2) 可以单独的进行最大化.

首先考虑 τ, 有条件τ1 + τ2=1:

和MLE的形式是类似的,二项分布 , 因此:

下一步估计 (μ1,Σ1):

和加权的 MLE就正态分布来说类似

 and 

对称的:

 and .

这个例子来自Answers.com的Expectation-maximization algorithm,由于还没有深入体验,心里还说不出一些更通俗易懂的东西来,等研究了并且应用了可能就有所理解和消化。另外,liuxqsmile也做了一些理解和翻译。

============

在网上的源码不多,有一个很好的EM_GM.m,是滑铁卢大学的Patrick P. C. Tsui写的,拿来分享一下:

运行的时候可以如下进行初始化:

  1. % matlab code
  2. X = zeros(,);
  3. X(:,:) = normrnd(,,,);
  4. X(:,:) = normrnd(,,,);
  5. X(:,:) = normrnd(,,,);
  6. [W,M,V,L] = EM_GM(X,,[],[],,[])

下面是程序源码:

  1. %matlab code
  2.  
  3. function [W,M,V,L] = EM_GM(X,k,ltol,maxiter,pflag,Init)
  4. % [W,M,V,L] = EM_GM(X,k,ltol,maxiter,pflag,Init)
  5. %
  6. % EM algorithm for k multidimensional Gaussian mixture estimation
  7. %
  8. % Inputs:
  9. % X(n,d) - input data, n=number of observations, d=dimension of variable
  10. % k - maximum number of Gaussian components allowed
  11. % ltol - percentage of the log likelihood difference between iterations ([] for none)
  12. % maxiter - maximum number of iteration allowed ([] for none)
  13. % pflag - for plotting GM for 1D or 2D cases only, otherwise ([] for none)
  14. % Init - structure of initial W, M, V: Init.W, Init.M, Init.V ([] for none)
  15. %
  16. % Ouputs:
  17. % W(,k) - estimated weights of GM
  18. % M(d,k) - estimated mean vectors of GM
  19. % V(d,d,k) - estimated covariance matrices of GM
  20. % L - log likelihood of estimates
  21. %
  22. % Written by
  23. % Patrick P. C. Tsui,
  24. % PAMI research group
  25. % Department of Electrical and Computer Engineering
  26. % University of Waterloo,
  27. % March,
  28. %
  29.  
  30. %%%% Validate inputs %%%%
  31. if nargin <= ,
  32. disp('EM_GM must have at least 2 inputs: X,k!/n')
  33. return
  34. elseif nargin == ,
  35. ltol = 0.1; maxiter = ; pflag = ; Init = [];
  36. err_X = Verify_X(X);
  37. err_k = Verify_k(k);
  38. if err_X | err_k, return; end
  39. elseif nargin == ,
  40. maxiter = ; pflag = ; Init = [];
  41. err_X = Verify_X(X);
  42. err_k = Verify_k(k);
  43. [ltol,err_ltol] = Verify_ltol(ltol);
  44. if err_X | err_k | err_ltol, return; end
  45. elseif nargin == ,
  46. pflag = ; Init = [];
  47. err_X = Verify_X(X);
  48. err_k = Verify_k(k);
  49. [ltol,err_ltol] = Verify_ltol(ltol);
  50. [maxiter,err_maxiter] = Verify_maxiter(maxiter);
  51. if err_X | err_k | err_ltol | err_maxiter, return; end
  52. elseif nargin == ,
  53. Init = [];
  54. err_X = Verify_X(X);
  55. err_k = Verify_k(k);
  56. [ltol,err_ltol] = Verify_ltol(ltol);
  57. [maxiter,err_maxiter] = Verify_maxiter(maxiter);
  58. [pflag,err_pflag] = Verify_pflag(pflag);
  59. if err_X | err_k | err_ltol | err_maxiter | err_pflag, return; end
  60. elseif nargin == ,
  61. err_X = Verify_X(X);
  62. err_k = Verify_k(k);
  63. [ltol,err_ltol] = Verify_ltol(ltol);
  64. [maxiter,err_maxiter] = Verify_maxiter(maxiter);
  65. [pflag,err_pflag] = Verify_pflag(pflag);
  66. [Init,err_Init]=Verify_Init(Init);
  67. if err_X | err_k | err_ltol | err_maxiter | err_pflag | err_Init, return; end
  68. else
  69. disp('EM_GM must have 2 to 6 inputs!');
  70. return
  71. end
  72.  
  73. %%%% Initialize W, M, V,L %%%%
  74. t = cputime;
  75. if isempty(Init),
  76. [W,M,V] = Init_EM(X,k); L = ;
  77. else
  78. W = Init.W;
  79. M = Init.M;
  80. V = Init.V;
  81. end
  82. Ln = Likelihood(X,k,W,M,V); % Initialize log likelihood
  83. Lo = *Ln;
  84.  
  85. %%%% EM algorithm %%%%
  86. niter = ;
  87. while (abs(*(Ln-Lo)/Lo)>ltol) & (niter<=maxiter),
  88. E = Expectation(X,k,W,M,V); % E-step
  89. [W,M,V] = Maximization(X,k,E); % M-step
  90. Lo = Ln;
  91. Ln = Likelihood(X,k,W,M,V);
  92. niter = niter + ;
  93. end
  94. L = Ln;
  95.  
  96. %%%% Plot 1D or 2D %%%%
  97. if pflag==,
  98. [n,d] = size(X);
  99. if d>,
  100. disp('Can only plot 1 or 2 dimensional applications!/n');
  101. else
  102. Plot_GM(X,k,W,M,V);
  103. end
  104. elapsed_time = sprintf('CPU time used for EM_GM: %5.2fs',cputime-t);
  105. disp(elapsed_time);
  106. disp(sprintf('Number of iterations: %d',niter-));
  107. end
  108. %%%%%%%%%%%%%%%%%%%%%%
  109. %%%% End of EM_GM %%%%
  110. %%%%%%%%%%%%%%%%%%%%%%
  111.  
  112. function E = Expectation(X,k,W,M,V)
  113. [n,d] = size(X);
  114. a = (*pi)^(0.5*d);
  115. S = zeros(,k);
  116. iV = zeros(d,d,k);
  117. for j=:k,
  118. if V(:,:,j)==zeros(d,d), V(:,:,j)=ones(d,d)*eps; end
  119. S(j) = sqrt(det(V(:,:,j)));
  120. iV(:,:,j) = inv(V(:,:,j));
  121. end
  122. E = zeros(n,k);
  123. for i=:n,
  124. for j=:k,
  125. dXM = X(i,:)'-M(:,j);
  126. pl = exp(-0.5*dXM'*iV(:,:,j)*dXM)/(a*S(j));
  127. E(i,j) = W(j)*pl;
  128. end
  129. E(i,:) = E(i,:)/sum(E(i,:));
  130. end
  131. %%%%%%%%%%%%%%%%%%%%%%%%%%%%
  132. %%%% End of Expectation %%%%
  133. %%%%%%%%%%%%%%%%%%%%%%%%%%%%
  134.  
  135. function [W,M,V] = Maximization(X,k,E)
  136. [n,d] = size(X);
  137. W = zeros(,k); M = zeros(d,k);
  138. V = zeros(d,d,k);
  139. for i=:k, % Compute weights
  140. for j=:n,
  141. W(i) = W(i) + E(j,i);
  142. M(:,i) = M(:,i) + E(j,i)*X(j,:)';
  143. end
  144. M(:,i) = M(:,i)/W(i);
  145. end
  146. for i=:k,
  147. for j=:n,
  148. dXM = X(j,:)'-M(:,i);
  149. V(:,:,i) = V(:,:,i) + E(j,i)*dXM*dXM';
  150. end
  151. V(:,:,i) = V(:,:,i)/W(i);
  152. end
  153. W = W/n;
  154. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  155. %%%% End of Maximization %%%%
  156. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  157.  
  158. function L = Likelihood(X,k,W,M,V)
  159. % Compute L based on K. V. Mardia, "Multivariate Analysis", Academic Press, , PP. -
  160. % to enchance computational speed
  161. [n,d] = size(X);
  162. U = mean(X)';
  163. S = cov(X);
  164. L = ;
  165. for i=:k,
  166. iV = inv(V(:,:,i));
  167. L = L + W(i)*(-0.5*n*log(det(*pi*V(:,:,i))) ...
  168. -0.5*(n-)*(trace(iV*S)+(U-M(:,i))'*iV*(U-M(:,i))));
  169. end
  170. %%%%%%%%%%%%%%%%%%%%%%%%%%%
  171. %%%% End of Likelihood %%%%
  172. %%%%%%%%%%%%%%%%%%%%%%%%%%%
  173.  
  174. function err_X = Verify_X(X)
  175. err_X = ;
  176. [n,d] = size(X);
  177. if n<d,
  178. disp('Input data must be n x d!/n');
  179. return
  180. end
  181. err_X = ;
  182. %%%%%%%%%%%%%%%%%%%%%%%%%
  183. %%%% End of Verify_X %%%%
  184. %%%%%%%%%%%%%%%%%%%%%%%%%
  185.  
  186. function err_k = Verify_k(k)
  187. err_k = ;
  188. if ~isnumeric(k) | ~isreal(k) | k<,
  189. disp('k must be a real integer >= 1!/n');
  190. return
  191. end
  192. err_k = ;
  193. %%%%%%%%%%%%%%%%%%%%%%%%%
  194. %%%% End of Verify_k %%%%
  195. %%%%%%%%%%%%%%%%%%%%%%%%%
  196.  
  197. function [ltol,err_ltol] = Verify_ltol(ltol)
  198. err_ltol = ;
  199. if isempty(ltol),
  200. ltol = 0.1;
  201. elseif ~isreal(ltol) | ltol<=,
  202. disp('ltol must be a positive real number!');
  203. return
  204. end
  205. err_ltol = ;
  206. %%%%%%%%%%%%%%%%%%%%%%%%%%%%
  207. %%%% End of Verify_ltol %%%%
  208. %%%%%%%%%%%%%%%%%%%%%%%%%%%%
  209.  
  210. function [maxiter,err_maxiter] = Verify_maxiter(maxiter)
  211. err_maxiter = ;
  212. if isempty(maxiter),
  213. maxiter = ;
  214. elseif ~isreal(maxiter) | maxiter<=,
  215. disp('ltol must be a positive real number!');
  216. return
  217. end
  218. err_maxiter = ;
  219. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  220. %%%% End of Verify_maxiter %%%%
  221. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  222.  
  223. function [pflag,err_pflag] = Verify_pflag(pflag)
  224. err_pflag = ;
  225. if isempty(pflag),
  226. pflag = ;
  227. elseif pflag~= & pflag~=,
  228. disp('Plot flag must be either 0 or 1!/n');
  229. return
  230. end
  231. err_pflag = ;
  232. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  233. %%%% End of Verify_pflag %%%%
  234. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  235.  
  236. function [Init,err_Init] = Verify_Init(Init)
  237. err_Init = ;
  238. if isempty(Init),
  239. % Do nothing;
  240. elseif isstruct(Init),
  241. [Wd,Wk] = size(Init.W);
  242. [Md,Mk] = size(Init.M);
  243. [Vd1,Vd2,Vk] = size(Init.V);
  244. if Wk~=Mk | Wk~=Vk | Mk~=Vk,
  245. disp('k in Init.W(1,k), Init.M(d,k) and Init.V(d,d,k) must equal!/n')
  246. return
  247. end
  248. if Md~=Vd1 | Md~=Vd2 | Vd1~=Vd2,
  249. disp('d in Init.W(1,k), Init.M(d,k) and Init.V(d,d,k) must equal!/n')
  250. return
  251. end
  252. else
  253. disp('Init must be a structure: W(1,k), M(d,k), V(d,d,k) or []!');
  254. return
  255. end
  256. err_Init = ;
  257. %%%%%%%%%%%%%%%%%%%%%%%%%%%%
  258. %%%% End of Verify_Init %%%%
  259. %%%%%%%%%%%%%%%%%%%%%%%%%%%%
  260.  
  261. function [W,M,V] = Init_EM(X,k)
  262. [n,d] = size(X);
  263. [Ci,C] = kmeans(X,k,'Start','cluster', ...
  264. 'Maxiter',, ...
  265. 'EmptyAction','drop', ...
  266. 'Display','off'); % Ci(nx1) - cluster indeices; C(k,d) - cluster centroid (i.e. mean)
  267. while sum(isnan(C))>,
  268. [Ci,C] = kmeans(X,k,'Start','cluster', ...
  269. 'Maxiter',, ...
  270. 'EmptyAction','drop', ...
  271. 'Display','off');
  272. end
  273. M = C';
  274. Vp = repmat(struct('count',,'X',zeros(n,d)),,k);
  275. for i=:n, % Separate cluster points
  276. Vp(Ci(i)).count = Vp(Ci(i)).count + ;
  277. Vp(Ci(i)).X(Vp(Ci(i)).count,:) = X(i,:);
  278. end
  279. V = zeros(d,d,k);
  280. for i=:k,
  281. W(i) = Vp(i).count/n;
  282. V(:,:,i) = cov(Vp(i).X(:Vp(i).count,:));
  283. end
  284. %%%%%%%%%%%%%%%%%%%%%%%%
  285. %%%% End of Init_EM %%%%
  286. %%%%%%%%%%%%%%%%%%%%%%%%
  287.  
  288. function Plot_GM(X,k,W,M,V)
  289. [n,d] = size(X);
  290. if d>,
  291. disp('Can only plot 1 or 2 dimensional applications!/n');
  292. return
  293. end
  294. S = zeros(d,k);
  295. R1 = zeros(d,k);
  296. R2 = zeros(d,k);
  297. for i=:k, % Determine plot range as x standard deviations
  298. S(:,i) = sqrt(diag(V(:,:,i)));
  299. R1(:,i) = M(:,i)-*S(:,i);
  300. R2(:,i) = M(:,i)+*S(:,i);
  301. end
  302. Rmin = min(min(R1));
  303. Rmax = max(max(R2));
  304. R = [Rmin:0.001*(Rmax-Rmin):Rmax];
  305. clf, hold on
  306. if d==,
  307. Q = zeros(size(R));
  308. for i=:k,
  309. P = W(i)*normpdf(R,M(:,i),sqrt(V(:,:,i)));
  310. Q = Q + P;
  311. plot(R,P,'r-'); grid on,
  312. end
  313. plot(R,Q,'k-');
  314. xlabel('X');
  315. ylabel('Probability density');
  316. else % d==
  317. plot(X(:,),X(:,),'r.');
  318. for i=:k,
  319. Plot_Std_Ellipse(M(:,i),V(:,:,i));
  320. end
  321. xlabel('1^{st} dimension');
  322. ylabel('2^{nd} dimension');
  323. axis([Rmin Rmax Rmin Rmax])
  324. end
  325. title('Gaussian Mixture estimated by EM');
  326. %%%%%%%%%%%%%%%%%%%%%%%%
  327. %%%% End of Plot_GM %%%%
  328. %%%%%%%%%%%%%%%%%%%%%%%%
  329.  
  330. function Plot_Std_Ellipse(M,V)
  331. [Ev,D] = eig(V);
  332. d = length(M);
  333. if V(:,:)==zeros(d,d),
  334. V(:,:) = ones(d,d)*eps;
  335. end
  336. iV = inv(V);
  337. % Find the larger projection
  338. P = [,;,]; % X-axis projection operator
  339. P1 = P * *sqrt(D(,)) * Ev(:,);
  340. P2 = P * *sqrt(D(,)) * Ev(:,);
  341. if abs(P1()) >= abs(P2()),
  342. Plen = P1();
  343. else
  344. Plen = P2();
  345. end
  346. count = ;
  347. step = 0.001*Plen;
  348. Contour1 = zeros(,);
  349. Contour2 = zeros(,);
  350. for x = -Plen:step:Plen,
  351. a = iV(,);
  352. b = x * (iV(,)+iV(,));
  353. c = (x^) * iV(,) - ;
  354. Root1 = (-b + sqrt(b^ - *a*c))/(*a);
  355. Root2 = (-b - sqrt(b^ - *a*c))/(*a);
  356. if isreal(Root1),
  357. Contour1(count,:) = [x,Root1] + M';
  358. Contour2(count,:) = [x,Root2] + M';
  359. count = count + ;
  360. end
  361. end
  362. Contour1 = Contour1(:count-,:);
  363. Contour2 = [Contour1(,:);Contour2(:count-,:);Contour1(count-,:)];
  364. plot(M(),M(),'k+');
  365. plot(Contour1(:,),Contour1(:,),'k-');
  366. plot(Contour2(:,),Contour2(:,),'k-');
  367. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  368. %%%% End of Plot_Std_Ellipse %%%%
  369. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

from: http://www.zhizhihu.com/html/y2010/2109.html

Expectation Maximization-EM(期望最大化)-算法以及源码的更多相关文章

  1. EM 期望最大化算法

    (EM算法)The EM Algorithm EM是我一直想深入学习的算法之一,第一次听说是在NLP课中的HMM那一节,为了解决HMM的参数估计问题,使用了EM算法.在之后的MT中的词对齐中也用到了. ...

  2. GWO(灰狼优化)算法MATLAB源码逐行中文注解(转载)

    以优化SVM算法的参数c和g为例,对GWO算法MATLAB源码进行了逐行中文注解. tic % 计时器 %% 清空环境变量 close all clear clc format compact %% ...

  3. SURF算法与源码分析、下

    上一篇文章 SURF算法与源码分析.上 中主要分析的是SURF特征点定位的算法原理与相关OpenCV中的源码分析,这篇文章接着上篇文章对已经定位到的SURF特征点进行特征描述.这一步至关重要,这是SU ...

  4. 6种基础排序算法java源码+图文解析[面试宝典]

    一.概述 作为一个合格的程序员,算法是必备技能,特此总结6大基础算法.java版强烈推荐<算法第四版>非常适合入手,所有算法网上可以找到源码下载. PS:本文讲解算法分三步:1.思想2.图 ...

  5. 十大基础排序算法[java源码+动静双图解析+性能分析]

    一.概述 作为一个合格的程序员,算法是必备技能,特此总结十大基础排序算法.java版源码实现,强烈推荐<算法第四版>非常适合入手,所有算法网上可以找到源码下载. PS:本文讲解算法分三步: ...

  6. SURF算法与源码分析、上

    如果说SIFT算法中使用DOG对LOG进行了简化,提高了搜索特征点的速度,那么SURF算法则是对DoH的简化与近似.虽然SIFT算法已经被认为是最有效的,也是最常用的特征点提取的算法,但如果不借助于硬 ...

  7. 三种排序算法python源码——冒泡排序、插入排序、选择排序

    最近在学习python,用python实现几个简单的排序算法,一方面巩固一下数据结构的知识,另一方面加深一下python的简单语法. 冒泡排序算法的思路是对任意两个相邻的数据进行比较,每次将最小和最大 ...

  8. Java数据结构和算法 - TreeMap源码理解红黑树

    前言 本篇将结合JDK1.6的TreeMap源码,来一起探索红-黑树的奥秘.红黑树是解决二叉搜索树的非平衡问题. 当插入(或者删除)一个新节点时,为了使树保持平衡,必须遵循一定的规则,这个规则就是红- ...

  9. faster rcnn算法及源码及论文解析相关博客

    1. 通过代码理解faster-RCNN中的RPN http://blog.csdn.net/happyflyy/article/details/54917514 2. faster rcnn详解 R ...

随机推荐

  1. ASP.NET MVC之Ajax如影随行

    一.Ajax的前世今生 我一直觉得google是一家牛逼的公司,为什么这样说呢?<舌尖上的中国>大家都看了,那些美食估计你是百看不厌,但是里边我觉得其实也有这样的一个哲学:关于食材,对于种 ...

  2. 【51nod】1564 区间的价值

    题解 这个要注意到一个长度大的区间的最大价值一定比长度小的区间的价值要大 然后我们以每个点为最小值,显然区间越长最大值越大,然后我们更新最大区间长度的取值,这个可以用单调栈求这个最小值能更新到的左右端 ...

  3. linux用户下的.profile文件丢失

    登录用户时出现以下问题: #su - wqq-bash-4.1$ -bash-4.1$ 查看时发现环境变量文件丢失造成的 解决方法: # ls -la /etc/skel/  total 36drwx ...

  4. Bunch 转换为 HDF5 文件:高效存储 Cifar 等数据集

    关于如何将数据集封装为 Bunch 可参考 关于 『AI 专属数据库的定制』的改进. PyTables 是 Python 与 HDF5 数据库/文件标准的结合.它专门为优化 I/O 操作的性能.最大限 ...

  5. CSUOJ 1224 ACM小组的古怪象棋

    Description ACM小组的Samsara和Staginner对中国象棋特别感兴趣,尤其对马(可能是因为这个棋子的走法比较多吧)的使用进行深入研究.今天他们又在 构思一个古怪的棋局:假如Sam ...

  6. 试水jdk8 stream

    jdk8出来日子不短了,jdk11都出来了,不过用的最多的不过是1.5罢了. 今年终于鼓起勇气认真对待它,在18年记录下学习stream,画上一个圆. 先看个图 Java8中有两大最为重要的改变.第一 ...

  7. 日报 18/07/15 Java 性能优化

    尽量指定类和方法的final修饰符 带有final修饰符的类是不可派生的 在java核心api中 有许多应用final的例子 例如 java.lang.string整个类都是final的 为类指定fi ...

  8. 【搜索+DP】codevs1066-引水入城

    [题目大意] 一个N行M列的矩形,如上图所示,其中每个格子都代表一座城 市,每座城市都有一个海拔高度.现在要在某些城市建造水利设施.水利设施有两种,分别为蓄水厂和输水站.蓄水厂的功能是利用水泵将湖泊中 ...

  9. Easy File Sharing Web Server 6.9远程溢出漏洞

    from struct import pack import socket,sys import os host="192.168.109.129" port=80 junk0 = ...

  10. [COGS2639]偏序++

    [COGS2639]偏序++ 题目大意: \(n(n\le40000)\)个\(k(k\le7)\)元组,求\(k\)维偏序. 思路: 分块后用bitset维护. 时间复杂度\(\mathcal O( ...