Deque

Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 731    Accepted Submission(s): 236

Problem Description
Today, the teacher gave Alice extra homework for the girl weren't attentive in his class. It's hard, and Alice is going to turn to you for help.

The teacher gave Alice a sequence of number(named A) and a deque. The sequence exactly contains N integers. A deque is such a queue, that one is able to push or pop the element at its front end or rear end. Alice was asked to take out the elements from the sequence in order(from A_1 to A_N), and decide to push it to the front or rear of the deque, or drop it directly. At any moment, Alice is allowed to pop the elements on the both ends of the deque. The only limit is, that the elements in the deque should be non-decreasing.

Alice's task is to find a way to push as many elements as possible into the deque. You, the greatest programmer, are required to reclaim the little girl from despair.

 
Input
The first line is an integer T(1≤T≤10) indicating the number of test cases.

For each case, the first line is the length of sequence N(1≤N≤100000).

The following line contains N integers A
1,A
2,…,A
N.

 
Output
For each test case, output one integer indicating the maximum length of the deque.
 
Sample Input
3
7
1 2 3 4 5 6 7
5
4 3 2 1 5
5
5 4 1 2 3
 
Sample Output
7
5
3
 
Source
 
Recommend
liuyiding
 

我直接附上标准题解吧。。当时是看出这是最长下降跟最长上升序列的求和的,只是因为没相处nlogn算法,最终没有做出来。 今天终于AC掉了。 刚开始考虑的时候,还是没有考虑到

5

5 5 5 5 5 这种需要过滤掉重复的方法,导致WA了很多次,后来多开了一个数组保留才AC掉。

标准题解是:

Problem E. Deque考虑题目的一个简化版本:使双端队列单调上升。对于序列 A 和队列 Q,找到队列中最早出现的数字Ax,则Ax将 Q 分成的两个部分分别是原序列中以Ax开始的最长上升和最长下降序列,答案即为这两者之和的最大值。而对于本题,由于存在相同元素,所以只要找到以Ax为起点的最长不下降序列和最长不上升序列的和,然后减去两个里面出现Ax 次数的最小值即可。

我的代码是:

/*
* @author ipqhjjybj
* @date 20130723
*/
#include <cstdio>
#include <cstdlib>
#include <cstring>
#define MAXN 100005
#define clr(x,k) memset((x),(k),sizeof(x))
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
int n;
int a[MAXN];
int d_p[MAXN]; //存储递减序列的数字
int d_f[MAXN];
int n_d_f[MAXN];//相同数字出现次数
int i_p[MAXN]; //存储递增序列的数字
int i_f[MAXN];
int n_i_f[MAXN];//相同数字出现次数
int find_dec(int l,int r,int x){
int i=l,j=r,mid;
while(i<=j){
mid=(i+j)>>1;
if(d_p[mid]<=x) i=mid+1;
else j=mid-1;
}return i;
}
int find_inc(int l,int r,int x){
int i = l,j=r,mid;
while(i<=j){
mid=(i+j)>>1;
if(i_p[mid]>=x) i=mid+1;
else j=mid-1;
}return i;
}
int main(){
//freopen("1005.in","r",stdin);
int z;
scanf("%d",&z);
while(z--){
clr(n_i_f,0),clr(n_d_f,0);
scanf("%d",&n);
for(int i = 1;i <= n;i++)
scanf("%d",&a[i]);
int ans=1;
int d_ans=1;
d_p[1]=a[n];
d_f[n]=1;
n_d_f[1]=1;
int i_ans=1;
i_p[1]=a[n];
i_f[n]=1;
n_i_f[1]=1;
for(int i=n-1;i>0;i--){
int t1=find_dec(1,d_ans,a[i]);
if(t1>d_ans)d_ans++;
d_p[t1]=a[i];
n_d_f[t1]=(t1>1&&d_p[t1-1]==a[i])?n_d_f[t1-1]+1:1;
d_f[i]=t1;
int t2=find_inc(1,i_ans,a[i]);
if(t2>i_ans)i_ans++;
i_p[t2]=a[i];
n_i_f[t2]=(t2>1&&i_p[t2-1]==a[i])?n_i_f[t2-1]+1:1;
i_f[i]=t2; //printf("m_t1=%d m_t2=%d\n",m_t1,m_t2);
int temp = t1+t2-min(n_d_f[t1],n_i_f[t2]);
ans = max(ans,temp);
}
printf("%d\n",ans);
}
return 0;
}

325MS过掉。。

附上标准程序

#include "iostream"
#include "cstring"
#include "cstdio"
#include "vector"
#include "algorithm"
#include "map"
using namespace std;
const int N = 100010;
int a[N];
int num_up[N],num_down[N];
int dp_up[N],dp_down[N];
int n;
void getdp(int dp[],int num[])
{
dp[n]=1;
vector<int> v;
v.push_back(a[n]);
vector<int>::iterator iter;
for(int i=n-1;i>=1;i--){
int sz=v.size();
if(a[i]>v[sz-1]){
v.push_back(a[i]);
dp[i]=sz+1;
num[i]=1;
}else if(a[i]==v[sz-1]){
iter=upper_bound(v.begin(),v.end(),a[i]);
dp[i]=iter-v.begin()+1;
v.push_back(a[i]);
pair<vector<int>::iterator,vector<int>::iterator> bounds;
bounds=equal_range(v.begin(),v.end(),a[i]);
num[i]=bounds.second-bounds.first;
}else{
iter=upper_bound(v.begin(),v.end(),a[i]);
dp[i]=iter-v.begin()+1;
*iter=a[i];
pair<vector<int>::iterator,vector<int>::iterator> bounds;
bounds=equal_range(v.begin(),v.end(),a[i]);
num[i]=bounds.second-bounds.first;
}
}
}
void debug(int a[])
{
for(int i=1;i<=n;i++){
printf("%d ",a[i]);
}
printf("\n");
}
int main(void)
{
int T;
scanf("%d",&T);
while(T--){
int ans=0;
scanf("%d",&n);
map<int,int> mp;
mp.clear();
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
}
getdp(dp_up,num_up);
for(int i=1;i<=n;i++){
a[i]=-a[i];
}
getdp(dp_down,num_down);
for(int i=1;i<=n;i++){
mp[a[i]]++;
ans=max(ans,dp_down[i]+dp_up[i]-min(num_up[i],num_down[i]));
}
printf("%d\n",ans);
}
return 0;
}

标准程序用了986MS。。。可能我的程序优化的还好点吧。。。

总而言之是水平不够。。当时没想出nlogn算法。。

多校联合练习赛1 Problem1005 Deque LIS+LDS 再加一系列优化的更多相关文章

  1. HDU 多校联合练习赛2 Warm up 2 二分图匹配

    Warm up 2 Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others) Total ...

  2. 2016暑假多校联合---Rikka with Sequence (线段树)

    2016暑假多校联合---Rikka with Sequence (线段树) Problem Description As we know, Rikka is poor at math. Yuta i ...

  3. 2016暑假多校联合---Windows 10

    2016暑假多校联合---Windows 10(HDU:5802) Problem Description Long long ago, there was an old monk living on ...

  4. 2016暑假多校联合---Substring(后缀数组)

    2016暑假多校联合---Substring Problem Description ?? is practicing his program skill, and now he is given a ...

  5. 2016暑假多校联合---To My Girlfriend

    2016暑假多校联合---To My Girlfriend Problem Description Dear Guo I never forget the moment I met with you. ...

  6. 2016暑假多校联合---A Simple Chess

    2016暑假多校联合---A Simple Chess   Problem Description There is a n×m board, a chess want to go to the po ...

  7. HDU 5792---2016暑假多校联合---World is Exploding

    2016暑假多校联合---World is Exploding Problem Description Given a sequence A with length n,count how many ...

  8. 2016暑假多校联合---Another Meaning

    2016暑假多校联合---Another Meaning Problem Description As is known to all, in many cases, a word has two m ...

  9. hdu 5288||2015多校联合第一场1001题

    pid=5288">http://acm.hdu.edu.cn/showproblem.php?pid=5288 Problem Description OO has got a ar ...

随机推荐

  1. NFC的安全性

    NFC近距离无线技术具有快捷.易用.安全等特性,其中安全是支付行业最关心的特性. 众所周知传统磁条银行卡的账号信息,是记录在磁条中,当进行刷卡交易时,POS机将交易金额,银行卡中的账号信息以及用户输入 ...

  2. Linux进程间通信——信号集函数

    一.什么是信号 用过Windows的我们都知道,当我们无法正常结束一个程序时,可以用任务管理器强制结束这个进程,但这其实是怎么实现的呢?同样的功能在Linux上是通过生成信号和捕获信号来实现的,运行中 ...

  3. -DDEBUG编译标记

    想必大家都有利用输出函数如printf来帮助我们调试程序的经历,这是一种比较原始的程序调试辅助方法,在Linux下也可以为我们所用.不过这种方法有一个明显的缺点,就是在调试完后我们必须注释或删除掉这些 ...

  4. iOS 堆和栈 的理解

    本文部分内容整理于网络,感谢原作者. 堆(heap)和栈(stack)是C/C++编程不可避免会碰到的两个基本概念.首先,这两个概念都可以在讲数据 结构的书中找到,他们都是基本的数据结构,虽然栈更为简 ...

  5. PHP 多input file文件上传

    前台html jquery代码 后台PHP处理 前台html <form id="form" method="post" enctype="mu ...

  6. Oracle11g重建EM 报ORA-20001: SYSMAN already exists

    日志: Apr , :: PM oracle.sysman.emcp.EMReposConfig createRepository : SYSMAN already exists.. ORA-0651 ...

  7. CSS权威指南学习笔记 —— 初步认识CSS

    层叠样式表(Cascading Style Sheets,CSS)可以影响文档的表现.CSS是依附于文档的,如果不存在某种文档,CSS基本上是没有用的. 为什么会有CSS 在web早期(1990-19 ...

  8. 浏览器的重绘(repaints)与重排(reflows)

    转:http://www.css88.com/archives/4991#more-4991 在项目的交互或视觉评审中,前端同学常常会对一些交互效果质疑,提出这样做不好那样做不好.主要原因是这些效果通 ...

  9. SQL Server数据恢复——日志备份

    太坑了,我把数据给删了 “大坑啊,数据被我误删了.”从事数据库相关工作的过程中,我想应该很多人会有过和我一样的遭遇吧?尤其是在进行update或者delete操作的时候,忘记了where条件.这些毁灭 ...

  10. IntPtr问题

    public aaa(IntPtr myPtr,int left, int top, int width, short height) 这里myPtr应该是对应到一块内存,你需要查看aaa函数是如何把 ...