题意是:给你一个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. C# 解决窗体假死的状态

    异步调用是CLR为开发者提供的一种重要的编程手段,它也是构建高性能.可伸缩应用程序的关键.在多核CPU越来越普及的今天,异步编程允许使用非常少的线程执行很多操作.我们通常使用异步完成许多计算型.IO型 ...

  2. 阿里云ECS linux通过rinetd 端口转发来访问内网服务

    一.场景说明: 可以通过端口映射的方式,来通过具有公网的云服务器 ECS 访问用户名下其它未购买公网带宽的内网 ECS 上的服务.端口映射的方案有很多,比如 Linux 下的 SSH Tunnel.r ...

  3. 怎样用Google APIs和Google的应用系统进行集成(4)----获得Access Token以通过一些Google APIs的OAuth2认证

    在上篇文章中: "怎样用Google APIs和Google的应用系统进行集成(3)----调用发现Google APIs的RESTful的服务"一文中,我们直接用jdk的java ...

  4. Ios 调用Appstore 下载界面 [[UIApplication sharedApplication] openURL

    http://phobos.apple.com/WebObjects/MZStore.woa/wa/viewSoftware?mt=8&id=286274367 id = itunesconn ...

  5. Django——Django,uwsgi Nginx组合建站

    近来抽时间看了点关于python的资料,试着架设了下运行环境,于是写了本文记录之. 用到的软件: Django-1.6.1 uwsgi-2.0.7 python-3.3.3 nginx-1.7.7 安 ...

  6. 放大的X 【杭电-2655】 附题

    /* 放大的X Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Su ...

  7. Android Camera 使用小结。两种方法:一是调用系统camera app,二是自己写camera程序。

    源文链接:http://www.cnblogs.com/franksunny/archive/2011/11/17/2252926.html Android Camera 使用小结 Android手机 ...

  8. 使用dynamic类型来优化反射

    什么是dynamic类型?微软给出的官方文档中这样解释:在通过 dynamic 类型实现的操作中,该类型的作用是绕过编译时类型检查. 改为在运行时解析这些操作. dynamic 类型简化了对 COM ...

  9. linux proc目录和常用操作

    ------------------------------------------------/proc----------------------------------------------- ...

  10. Java线程安全同步容器

    线程安全同步容器(使用 synchronized关键字) 1.ArrayList->Vector,Stack 2.HashMap->HashTable(key.value不能为null) ...