6058 Kanade's sum

Kanade's sum

Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 1789    Accepted Submission(s): 728


Problem Description
Give you an array A[1..n] of length n .

Let f(l,r,k) be the k-th largest element of A[l..r] .

Specially , f(l,r,k)=0 if rl+1<k .

Give you k , you need to calculate nl=1nr=lf(l,r,k)

There are T test cases.

1T10

kmin(n,80)

A[1..n] is a permutation of [1..n]

n5105
 

Input
There is only one integer T on first line.

For each test case,there are only two integers n , k on first line,and the second line consists of n integers which means the array A[1..n]
 

Output
For each test case,output an integer, which means the answer.
 

Sample Input
  
1 5 2 1 2 3 4 5
 

Sample Output
  
30
 

Source

2017 Multi-University Training Contest - Team 3 

自己做的时候想不通 看了别人的题解 怎么人家这么聪明呢qaq 

直通车:http://blog.youkuaiyun.com/yjf3151731373/article/details/76559550


题意:A 中所有区间内第K大的数求和

分析:遍历A中所有元素 令当前元素为第K大 往右找 上限 再往左找下限 具体看代码qaq


AC:

#include <algorithm>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <cmath>
typedef long long LL;
using namespace std;
const int N=1e6;
const LL mod=1e9+7;
int a[N]={0};
int b[N]={0};
int main()
{
    int t;scanf("%d",&t);
    while(t--)
    {
       int n,k;scanf("%d%d",&n,&k);
       for(int i=1;i<=n;i++)scanf("%d",&a[i]);
       LL ans=0;
       //当前为第i大;
       for(int i=1;i<=n;i++)
       {
           int x=a[i],num=0,d=0,j;
           LL sum=0;

           b[++d]=i;//记位置
           for(j=i+1;j<=n&&d<k;j++)if(a[j]>x)b[++d]=j;

           if(d==k)//右边存a[j]>x使x成为第k大的数
           {
                num=1; //b当前区间算一个区间
                //算后面比它小的数量
                for(;j<=n;j++){
                    if(a[j]<x)num++;
                    else break;
                }

                sum+=num;
                //算前面比它小的数和比它大的数(前遇到一个比它大的数 后面比它大的数前进一个)

                for(j=i-1;j>=1&&d>=1;j--)
                {
                    if(a[j]<x)sum+=num;  //因为x是第二大的数区间不能跑到x左边 所以加上x右边的num
                    else
                    {
                        if(d==1)break;//b[1]就是本身 此时在右边界 不能左移了;

                        num=b[d]-b[d-1]; //右边比它大的数去掉一个区间
                        d--;
                        sum+=num;
                    }
                }
           }
           else{ //右边不存在
                for(j=i-1;j>=1&&d<k;j--)if(a[j]>x)b[++d]=j;
                if(d==k)
                {
                    sort(b+1,b+d+1);//
                    num=n-b[d]+1; //n-最大位置+1 = 右边比它大的最后一个位置右边比它小(a[j]<x)的数量;
                    sum+=num;
                    for(;j>=1&&b[d]>=i;j--)
                    {
                        if(a[j]<x)sum+=num;
                        else
                        {
                            if(b[d]==i)break;// i为右边界
                            num=abs(b[d]-b[d-1]);
                            d--;
                            sum+=num;
                        }
                    }
                }
           }
           ans+=x*sum;//sum为区间数
       }
       printf("%lld\n",ans);
    }
    return 0;
}


<think>好的,用户现在想要用MATLAB实现基于NMF的人脸表情识别程序,处理CK+数据集。首先,我需要回顾之前的对话,确保这次回答符合用户的需求。 用户之前询问了CK+数据集的下载方式,我详细介绍了官方渠道和第三方资源,并提到了数据验证和预处理的方法。现在用户的问题更具体,涉及到如何使用MATLAB加载数据集、应用NMF进行训练和测试。 首先,我需要确保用户正确加载数据集。之前提到过CK+的数据结构,包括图像和标签。用户需要解压extended-cohn-kanade-images.zip和Emotion_labels.zip,可能需要指导他们如何正确读取这些文件,尤其是处理目录结构。MATLAB中可能需要使用dir函数遍历文件夹,读取图像和标签。 接下来是数据预处理部分。CK+数据集中的图像可能尺寸不一,需要调整到统一大小,比如48x48,并转换为灰度图像。用户可能需要使用imresize和rgb2gray函数进行处理。此外,数据增强可能也是必要的,比如翻转或添加噪声,但用户的问题中没有提到,暂时可以放在扩展建议里。 然后是NMF的实现。NMF在MATLAB中有内置函数nnmf,但用户可能需要自己编写以更灵活地调整参数。需要解释如何将图像数据转换为非负矩阵,应用NMF分解得到基矩阵和系数矩阵。这里要注意非负矩阵的构造,可能需要将图像矩阵展平为向量,组合成一个大矩阵。 特征提取部分,系数矩阵可以作为特征向量,用于分类。分类器可以选择SVM,MATLAB中有fitcecoc函数适合多分类问题。需要指导用户如何划分训练集和测试集,通常70-30的比例,并确保数据随机打乱以避免偏差。 验证和测试阶段,需要计算准确率、混淆矩阵等指标。混淆矩阵可以用confusionmat实现,可视化可以帮助用户理解模型表现。可能还需要提醒用户注意过拟合问题,建议使用交叉验证,比如cvpartition。 引用部分,之前提到过两篇关键论文,这里需要再次强调正确的引用格式,确保用户遵守学术规范。同时,用户可能需要扩展方法,比如使用深度NMF或结合其他特征,这些可以作为优化建议提供。 用户可能遇到的问题包括路径错误、标签文件不匹配、内存不足等,应该在注意事项里提醒。此外,处理时间可能较长,建议预加载数据或使用并行计算。 需要检查之前的回答是否有遗漏,比如预处理中的具体代码示例,数据增强方法,以及如何解决类别不平衡问题。CK+可能有不同数量的样本 per 情绪,可能需要提及重采样或其他策略。 最后,确保回答结构清晰,分步骤指导,代码可运行,并解释关键步骤的作用。同时,相关问题要针对NMF和表情识别,引导用户深入探索。</think>### 基于NMF的CK+人脸表情识别MATLAB实现指南 #### 一、数据加载与预处理 ```matlab %% 数据加载核心代码 dataDir = 'CK_Extended'; imgDir = fullfile(dataDir,'cohn-kanade-images'); labelDir = fullfile(dataDir,'Emotion'); % 加载图像路径 imgPaths = dir(fullfile(imgDir,'**','*.png')); % 包含593个序列的9,574帧 % 加载情感标签 labelMap = containers.Map; labelFiles = dir(fullfile(labelDir,'**','*.txt')); for f = 1:length(labelFiles) key = strrep(labelFiles(f).folder, labelDir, ''); labelMap(key) = textread(fullfile(labelFiles(f).folder, labelFiles(f).name)); end ``` #### 二、NMF特征提取 ```matlab %% 非负矩阵分解实现 function [W,H] = nmf_facial(V, k, max_iter) % 输入:V-图像矩阵(48x48xN -> 2304xN), k-基数量, max_iter-迭代次数 % 输出:W-基矩阵, H-系数矩阵 [m,n] = size(V); W = abs(randn(m,k)); % 初始化非负基矩阵 H = abs(randn(k,n)); % 初始化非负系数矩阵 for iter = 1:max_iter % 更新规则(Lee-Seung算法) H = H .* (W'*(V./(W*H+eps))) ./ (W'*ones(size(V))+eps); W = W .* ((V./(W*H+eps))*H') ./ (ones(size(V))*H'+eps); end end % 构造非负矩阵(示例) imgMatrix = zeros(48*48, 1000); % 假设选取1000个样本 for i = 1:1000 img = im2double(rgb2gray(imread(imgPaths(i).name))); imgMatrix(:,i) = img(:); end [W,H] = nmf_facial(imgMatrix, 50, 200); % 分解为50个基 ``` #### 三、分类器构建(SVM示例) ```matlab %% 特征向量构建与分类 labels = cell2mat(values(labelMap)); % 获取对应标签 features = H'; % 使用系数矩阵作为特征 % 数据集划分(7:3比例) cv = cvpartition(labels,'HoldOut',0.3); trainData = features(cv.training,:); testData = features(cv.test,:); % 多分类SVM训练 model = fitcecoc(trainData, labels(cv.training), ... 'Learners', templateSVM('KernelFunction','rbf')); % 预测与评估 pred = predict(model, testData); acc = sum(pred == labels(cv.test))/numel(pred); disp(['准确率: ',num2str(acc*100),'%']); %% 混淆矩阵可视化 confMat = confusionmat(labels(cv.test), pred); heatmap(confMat, 'XLabel','预测类别','YLabel','真实类别'); ``` #### 四、关键参数优化建议 1. **NMF基数量选择**: $$ \min_{k} \|V - WH\|_F^2 + \lambda(k) $$ 通过肘部法则确定最佳k值(建议范围30-100) 2. **数据增强策略**: ```matlab % 在线增强(训练时实时生成) augmentedImg = imnoise(imrotate(img, randi([-15,15]),'bilinear'),'gaussian'); ``` 3. **多尺度特征融合**: ```matlab pyramidFeatures = []; for scale = [1, 0.7, 0.5] resizedImg = imresize(img, scale); pyramidFeatures = [pyramidFeatures; resizedImg(:)]; end ``` #### 五、性能提升技巧 1. **动态加权NMF**: $$ W_{ij} \leftarrow W_{ij} \frac{(VH^T)_{ij}}{(WHH^T)_{ij}} \cdot \frac{1}{1+e^{-\alpha t}} $$ 其中α为时间衰减因子 2. **标签分布优化**: ```matlab % 类别平衡加权 classWeight = 1./countcats(labels); model = fitcecoc(...,'Weights',classWeight(labels)); ``` 3. **GPU加速实现**: ```matlab gpuV = gpuArray(V); [gpuW, gpuH] = nmf_facial(gpuV, ...); W = gather(gpuW); H = gather(gpuH); ``` #### 六、学术引用规范 必须包含以下参考文献: 1. Lee D D, Seung H S. "Algorithms for non-negative matrix factorization"[^1] 2. Lucey P, et al. "The Extended Cohn-Kanade Dataset (CK+): A complete dataset for action unit and emotion-specified expression"[^2] [^1]: NIPS 2000会议论文,提出经典NMF算法 [^2]: CVPR 2010 Workshop论文,CK+数据集基准文献
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值