timus1965(不错的贪心)
题意是:给你一个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(不错的贪心)的更多相关文章
- hdu4450 不错的贪心
题意: 卡片游戏 Time Limit: 3000/1000 MS (Java/Others) Memory Limit: 65535/32768 K (Java/Others) Total S ...
- BZOJ4977: [[Lydsy1708月赛]跳伞求生(不错的贪心)
4977: [[Lydsy1708月赛]跳伞求生 Time Limit: 5 Sec Memory Limit: 256 MBSubmit: 446 Solved: 142[Submit][Sta ...
- BZOJ3016: [Usaco2012 Nov]Clumsy Cows
3016: [Usaco2012 Nov]Clumsy Cows Time Limit: 1 Sec Memory Limit: 128 MBSubmit: 71 Solved: 52[Submi ...
- The 16th Zhejiang provincial collegiate programming contest
今天我挺有状态的,看过的题基本都给了正解(可能是昨晚cf div3打得跟屎一样,人品守恒,不好意思发题解了),自己也给队伍签了很多水题(不敢让队友写,怕出锅). 最后6题滚了,有点可惜.还差B和K没做 ...
- jzyz 题库 题目选做
题库中也有很多我想不出来的模拟赛的题目.做还是必要的.做自己的题目 时间很紧 想想自己的文化课 我又没有那么强 我必须得刷. LINK:水题一道 发现是一道计数题 计数题拿高分的才是王者,但是 计数题 ...
- POJ3040给奶牛发工资
题意: 有n种硬币,每种硬币有mi个,然后让你给奶牛发工资,每周发至少c元(就是不找零钱的意思)然后问你能发几周?(硬币之间都是倍数关系) 思路: 这个题目做了两天,丢脸,看完 ...
- [考试总结]noip模拟43
这个题目出的还是很偷懒.... 第一题...第二题...第三题...四.... 好吧... 这几次考得都有些问题,似乎可能是有些疲惫,脑袋也是转不太动,考完总觉得自己是能力的问题,但是改一分钟之后会发 ...
- SPOJ:Decreasing Number of Visible Box(不错的,背包?贪心?)
Shadowman loves to collect box but his roommates woogieman and itman don't like box and so shadowman ...
- SPOJ:Strange Waca(不错的搜索&贪心&剪枝)
Waca loves maths,.. a lot. He always think that 1 is an unique number. After playing in hours, Waca ...
随机推荐
- Java8 CompletableFuture组合式的编程(笔记)
* 实现异步API public double getPrice(String product) { return calculatePrice(product); } /** * 同步计算商品价格的 ...
- LInux——安装Apache
在安装Apache的httpd的时候经常会遇到: configure: error: APR not found . Please read the documentation. configure ...
- jQuery (样式篇)
1.$(document).ready 的作用是等页面的文档(document)中的节点都加载完毕后,再执行后续的代码,因为我们在执行代码的时候,可能会依赖页面的某一个元素,我们要确保这个元素真正的的 ...
- WP8数据存储--独立存储文件
主要的三个步骤 1.调用手机的独立存储 例如:IsolatedStorageFile storage = IsolatedStorageFile.GetUserStoreForApplication( ...
- iDempiere的用户密码加密处理(AD_User.Password)(Postgresql 9.1)
怀揣着为中小企业量身定做一整套开源软件解决方案的梦想开始了一个网站的搭建.http://osssme.org/ 首先对Postgresql数据库进行加密处理. 参考网页:francs写的:Postgr ...
- FD_SET 详解
http://blog.csdn.net/stephen_yin/article/details/7441165
- html标签说明
dictype 不区分大小写 HTML 4.01 与 HTML5 之间的差异 在 HTML 4.01 中有三种 <!DOCTYPE> 声明.在 HTML5 中只有一种: <!DOCT ...
- Git使用笔记2
工作必备: [更新master] git checkout master git pull git checkout zyb/FirstCommit git merge master //git re ...
- [原创]JAVA号码工具类:实现手机固话号码判断与区号截取
工具类说明 该工具类主要是用于判断号码的类型,如果是手机类型,则返回号码前7位,便于后面继续判断号码归属地:如果是固话类型,则截取固话的区号,同样也是为了后面判断号码的归属地. 在获取到这些信息之后, ...
- rxjs来啦
var text = document.querySelector('#text'); var inputStream = Rx.Observable.fromEvent(text, 'keyup') ...