题意是:给你一个1-n的排列,要你把这个排列分成两个序列,且这个两个序列都满足单调性。

题解:

1.首先假设找出的两个序列都是单调递增的(都是单调递减的同理)

那么很容易可以想到,将新加入的数放入到某个序列尾端,使得另一个序列尾端的数尽量小。

2.如果最后的两个序列为一个递增一个递减。

这种情况下,有一种眼光稍微长远一些的贪心策略。

假设当前要加入的数g[x],如果g[x]既可以放入单增序列中也可以放入单减序列中,则与g[x+1]比较。

if(g[x]>g[x+1]) 把g[x]放入单减序列中

else 把g[x]放入单增序列中

为什么这样贪心就行了?

可以做一个假设,当g[x]>g[x+1],我们却把g[x]放入单增序列中,则g[x]只能放入单减序列,最后得出的两个序列的尾部为:

xxxxg[x]    (单增序列)        。。。。。。。。。方法一

xxxxxxg[x+1] (单减序列)

而当我们把g[x]放入单减序列时,此时g[x+1]可能放入单增序列中,一定可以放入单减序列中,

1.如果g[x+1] 放入单减序列中,得出两个序列尾部为:

xxxX        (单增序列)    。。。。。。。。。方法二

xxxxxxg[x]g[x+1]  (单减序列)

而X<g[x] ,所以下面这种方法得出的结果一定优于方法一。

2.如果g[x+1]能放入单增序列,放入其中得出的两个序列尾部为:

xxxxg[x+1]  (单增序列)        。。。。。。。。。方法三

xxxxxxg[x]  (单减序列)

因为g[x]>g[x+1],所以结果一定优于方法一。

把眼界放开,即使是贪心也能贪的漂亮!

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define maxN 100005
const int inf=~0U>>;
int s1[maxN];
int f[maxN][];
int N,len1,len2;
bool judge1()
{
f[][]=f[][]=-;
len1=len2=;
for(int i=;i<=N;i++)
{
if(s1[i]<f[len1][]&&s1[i]<f[len2][])
return false;
else if(s1[i]>f[len1][]&&s1[i]<f[len2][])
f[++len1][]=s1[i];
else if(s1[i]<f[len1][]&&s1[i]>f[len2][])
f[++len2][]=s1[i];
else
{
if(f[len2][]>f[len1][]) f[++len2][]=s1[i];
else f[++len1][]=s1[i];
}
}
if(len1==N) f[++len2][]=f[len1--][];
return true;
}
bool judge2()
{
f[][]=f[][]=inf;
len1=len2=;
for(int i=;i<=N;i++)
{
if(s1[i]>f[len1][]&&s1[i]>f[len2][])
return false;
else if(s1[i]>f[len1][]&&s1[i]<f[len2][])
f[++len2][]=s1[i];
else if(s1[i]<f[len1][]&&s1[i]>f[len2][])
f[++len1][]=s1[i];
else
{
if(f[len2][]<f[len1][]) f[++len2][]=s1[i];
else f[++len1][]=s1[i];
}
}
if(len1==N) f[++len2][]=f[len1--][];
return true;
}
bool judge3()
{
len1 = len2 = ;
f[len1][]=-;
f[len2][]=inf;
for(int i=;i<=N;i++)
{
if(s1[i]<f[len1][]&&s1[i]>f[len2][]) return false;
else if(s1[i]>f[len1][]&&s1[i]<f[len2][])
{
if(i==N) f[++len1][]=s1[i];
else if(s1[i+]>s1[i]) f[++len1][]=s1[i];
else f[++len2][]=s1[i];
}
else if(s1[i]>f[len1][])
f[++len1][]=s1[i];
else
f[++len2][]=s1[i];
}
return true;
}
int main()
{
scanf("%d",&N);
for(int i=,j=N;i<=N;i++,j--)
{
scanf("%d",&s1[i]);
}
if(judge1())
{
printf("%d %d\n",len1,len2);
for(int i=;i<=len1;i++) printf("%d%c",f[i][],i==len1?'\n':' ');
for(int i=;i<=len2;i++) printf("%d%c",f[i][],i==len2?'\n':' ');
return ;
}
if(judge2())
{
printf("%d %d\n",len1,len2);
for(int i=;i<=len1;i++) printf("%d%c",f[i][],i==len1?'\n':' ');
for(int i=;i<=len2;i++) printf("%d%c",f[i][],i==len2?'\n':' ');
return ;
}
if(judge3())
{
printf("%d %d\n",len1,len2);
for(int i=;i<=len1;i++) printf("%d%c",f[i][],i==len1?'\n':' ');
for(int i=;i<=len2;i++) printf("%d%c",f[i][],i==len2?'\n':' ');
return ;
}
printf("Fail\n");
//print1(dp1[len1]);
//printf("\n");
//print2(dp2[len2]);
return ;
}

另加一个,我自己想的丑陋的贪心。。。

//
// main.cpp
// timus1965
//
// Created by 陈加寿 on 16/3/16.
// Copyright © 2016年 chenhuan001. All rights reserved.
// #include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <vector>
#include <map>
#include <set>
#include <math.h>
#include <algorithm>
using namespace std;
#define N 100100 int g[N],tg[N];
int ans1[N],ans2[N];
int cnt1,cnt2;
int n;
int b1,d1,b2,d2; int fuc()
{
cnt1 = cnt2 =;
//->
ans2[] = ;
ans1[ ++cnt1 ] = g[];
for(int i=;i<=n;i++)
{
if(g[i]<ans1[cnt1] && g[i]<ans2[cnt2])
{
return ;
}
//否则选尽量大的一边
if(g[i]>ans1[cnt1]) ans1[++cnt1]=g[i];
else ans2[++cnt2]=g[i];
}
return ;
} int fuc1()
{
cnt1 = cnt2 =;
//<-
ans2[] = n+;
ans1[ ++cnt1 ] = g[];
for(int i=;i<=n;i++)
{
if(g[i]>ans1[cnt1] && g[i]>ans2[cnt2])
{
return ;
}
//否则选尽量小的一边
if(g[i]<ans1[cnt1]) ans1[++cnt1]=g[i];
else ans2[++cnt2]=g[i];
}
return ;
} int test1(int b,int d)
{
if( tg[d]<b1 || tg[d]>d1 ) return ;// g[i]无法放入ans1中
//把(b,d)间的数全部放入ans2中去
//首先保证(b,d)之间是递减的
if(b+ == d)
{
ans1[++cnt1] = d;
b1 = tg[d];
return ;
}
for(int i=d-;i>b;i--)
{
if(tg[i]<tg[i+]) return ;//并不递减
}
if( tg[d-]>b2 && tg[b+]<d2 )
{
for(int i=d-;i>b;i--)
ans2[++cnt2] = i;
ans1[++cnt1] = d;
d2=tg[d-];
b1 = tg[d];
return ;
}
else return ;
} int test2(int b,int d)
{
if(tg[b]<b2 || tg[b]>d2) return ;
if(b+ == d)
{
ans2[++cnt2] = b;
b2 = tg[b];
return ;
}
for(int i=b+;i<d-;i++)
{
if(tg[i]>tg[i+]) return ;
}
if(tg[b+]>b1 && tg[d-]<d1)
{
for(int i=d-;i>b;i--)
ans1[++cnt1] = i;
ans2[++cnt2] = b;
d1 = tg[b+];
b2 = tg[b];
return ;
}
else return ;
} int solve()
{
int b=,d=n+;
b1=,d1=n+;
b2=,d2=n+;
//并不需要set
for(int i=;i<=n;i++)
{
if( g[i]<b || g[i]>d) continue; //已经处理过的,不再处理
if(g[i]-b < d-g[i])
{
//靠左,g[i]放入ans1中
if( test1(b,g[i])== )
{
//如果
b = g[i];
}
else if(test2(g[i],d)==)
{
d = g[i];
}
else return ;//两个测试都不过 直接返回不行.
}
else
{
//靠右
if(test2(g[i],d)==)
{
d=g[i];
}
else if(test1(b, g[i])==)
{
b=g[i];
}
else return ;
}
}
return ;
} int cmp(int x,int y)
{
return x>y;
} int main() {
cin>>n; for(int i=;i<=n;i++)
{
scanf("%d",g+i);
tg[ g[i] ] = i;
}
g[]=; g[n+]=n+;
tg[]=; tg[n+]=n+;
cnt1 = cnt2 = ;
int flag=;
//step one tha same direction
if( fuc() || fuc1() )
{
flag=;
}
if(flag == )
{
// step two the different direction
cnt1 = cnt2 =;
flag = solve();
//最后再sort一下
sort(ans1+,ans1++cnt1);
sort(ans2+,ans2++cnt2,cmp);
}
if(flag == )
{
printf("Fail\n");
}
else
{
//输出答案
if(cnt1==n)
{
ans2[++cnt2] = ans1[cnt1--];
}
if(cnt2==n)
{
ans1[++cnt1] = ans2[cnt2--];
}
cout<<cnt1<<" "<<cnt2<<endl;
for(int i=;i<=cnt1;i++) printf("%d ",ans1[i]);
printf("\n");
for(int i=;i<=cnt2;i++) printf("%d ",ans2[i]);
printf("\n");
}
return ;
}

timus1965(不错的贪心)的更多相关文章

  1. hdu4450 不错的贪心

    题意: 卡片游戏 Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others) Total S ...

  2. BZOJ4977: [[Lydsy1708月赛]跳伞求生(不错的贪心)

    4977: [[Lydsy1708月赛]跳伞求生 Time Limit: 5 Sec  Memory Limit: 256 MBSubmit: 446  Solved: 142[Submit][Sta ...

  3. BZOJ3016: [Usaco2012 Nov]Clumsy Cows

    3016: [Usaco2012 Nov]Clumsy Cows Time Limit: 1 Sec  Memory Limit: 128 MBSubmit: 71  Solved: 52[Submi ...

  4. The 16th Zhejiang provincial collegiate programming contest

    今天我挺有状态的,看过的题基本都给了正解(可能是昨晚cf div3打得跟屎一样,人品守恒,不好意思发题解了),自己也给队伍签了很多水题(不敢让队友写,怕出锅). 最后6题滚了,有点可惜.还差B和K没做 ...

  5. jzyz 题库 题目选做

    题库中也有很多我想不出来的模拟赛的题目.做还是必要的.做自己的题目 时间很紧 想想自己的文化课 我又没有那么强 我必须得刷. LINK:水题一道 发现是一道计数题 计数题拿高分的才是王者,但是 计数题 ...

  6. POJ3040给奶牛发工资

    题意:       有n种硬币,每种硬币有mi个,然后让你给奶牛发工资,每周发至少c元(就是不找零钱的意思)然后问你能发几周?(硬币之间都是倍数关系) 思路:       这个题目做了两天,丢脸,看完 ...

  7. [考试总结]noip模拟43

    这个题目出的还是很偷懒.... 第一题...第二题...第三题...四.... 好吧... 这几次考得都有些问题,似乎可能是有些疲惫,脑袋也是转不太动,考完总觉得自己是能力的问题,但是改一分钟之后会发 ...

  8. SPOJ:Decreasing Number of Visible Box(不错的,背包?贪心?)

    Shadowman loves to collect box but his roommates woogieman and itman don't like box and so shadowman ...

  9. SPOJ:Strange Waca(不错的搜索&贪心&剪枝)

    Waca loves maths,.. a lot. He always think that 1 is an unique number. After playing in hours, Waca ...

随机推荐

  1. Android SVG动画PathView源代码解析与使用教程(API 14)

    使用的是一个第三方库android-pathview主要是一个自己定义View--PathView.跟全部自己定义View一样,重写了三个构造方法. 而且终于调用三个參数的构造方法,在里面获取自己定义 ...

  2. openerp-server.conf 中配置 dbfilter 参数无效的解决办法

    来自:http://shine-it.net/index.php/topic,14517.html 以前就发现过这个问题, 今天重新在群里同大家讨论了一下. 有时候可能我们希望用户不从登陆界面的账套选 ...

  3. GCM与C2DM相比有什么不同

    eoe介绍:http://wiki.eoe.cn/page/Migration.html 官方地址:http://developer.android.com/google/gcm/c2dm.html

  4. 向 mysql 插入汉字时报错 Incorrect string value: '\xE6\x9B\xB9\xE5\x86\xAC...' for col....

    Incorrect string value: '\xE6\x9B\xB9\xE5\x86\xAC...' for column 'realname' at row 1 该情况一般是由数据库设计时的编 ...

  5. 轻量级代码生成器-OnlyCoder 第一篇

    程序猿利器:代码生成器,使用代码生成器已经好几年了,增删改查各种生成,从UI到DATA层均生成过.之前有使用过动软的,T4模板等....  T4生成实体还是没有问题的,但是生成MVC视图就有点烦杂了, ...

  6. C/C++中,空数组、空类、类中空数组的解析及其作用

    转自:http://blog.sina.com.cn/s/blog_93b45b0f01015s95.html 我们经常会遇到这些问题: (1)C++中定义一个空类,他们它的大小(sizeof) 为多 ...

  7. nginx.conf 详细

    ##定义nginx运行的用户各用户组user nginx nginx; ##nginx进程数,建议设置与cpu核心数一致worker_processes 1; ##全局错误日志定义类型[ debug ...

  8. 经过Nginx代理后如何区分HTTP请求头中的X-Forwarded-For和X-Real-IP,以及Java示例

    在开发工作中,我们常常需要获取客户端的IP.一般获取客户端的IP地址的方法是:request.getRemoteAddr();但是在通过了Apache,Squid等反向代理软件就不能获取到客户端的真实 ...

  9. 编辑HTML代码,批量制作博文清单

    当积累的博文多了,常想制作一个分类文件夹,方便读者阅读.这能够是一个不轻松且枯燥的工作. 以<关于"IT学子成长指导"专栏及文章文件夹>中文件夹的制作为例.介绍我的&q ...

  10. python 旧类中使用property特性的方法

    在python中,我们可以拦截对象的所有特性访问.通过这种拦截的思路,我们可以在旧式类中实现property方法. __getattribute__(self, name) #当特性name被访问时自 ...