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 ...
随机推荐
- 转:TensorFlow和Caffe、MXNet、Keras等其他深度学习框架的对比
http://geek.csdn.net/news/detail/138968 Google近日发布了TensorFlow 1.0候选版,这第一个稳定版将是深度学习框架发展中的里程碑的一步.自Tens ...
- EffectiveJava(25)泛型和数组的使用取舍及规范
泛型和数组 泛型:1.泛型是不可变的.对于任意两个不同类型Type1,type2;List既不是List的子类型,也不是List的超类型 2.泛型是通过擦除来实现的.故泛型只在编译时强化它们的信息,并 ...
- EffectiveJava(24)使用@SuppressWarnings("unchecked")消除非受检警告
-..使用泛型编程时,会遇到许多编译器警告,如:非受检强制转化警告,非受检方法调用警告,非受检普通数组创建警告,费受精转换警告.这次的内容就是遇到这些警告的时候你该怎么办. PS:非受检警告就是代码上 ...
- Java8:纠结的默认方法
[编程导论(Java)·4.3Java接口] 在[0.3.1 Java简单介绍]中,有这么一段话:"请注意:Java并不是作为教学语言设计的.世界各地的大学在讲授Java的过程中均遇到一些教 ...
- homestead虚拟机,通过npm下载依赖包和解决运行gulp报错问题 yarn出错问题
homestead虚拟机,通过npm下载依赖包和解决运行gulp报错问题 yarn出错问题 1. 在虚拟器运行 npm 下载依赖组件时报错: npm ERR! EPROTO: protocol err ...
- C++高级进阶 第四季:const具体解释(二) 常量折叠
一.文章来由 const具体解释之二 二.const 取代 #define const最初动机就是取代 #define. const 优于 #define: (1) #define没有类型检查,con ...
- centos mysql iptables配置
在CentOS系统中防火墙默认是阻止3306端口的,我们要是想访问mysql数据库,我们需要这个端口,命令如下: iptables -I INPUT -p tcp --dport 3036 -j AC ...
- Android布局中match_parent和fill_parent的差别
今天在做项目的一个新功能的时候,从网上查找资源,发现android2.2中出现的MATCH_PARENT感到不明确.过去仅仅有FILL_PARENT和WRAP_CONTENT那么match_paren ...
- hive 用户订单行为 基础操作
今天用hive查询用户日志表.这是日志表的格式: user_id,item_id,cat_id,merchant_id,brand_id,month,day,action,age_range,gend ...
- NIO之管道 (Pipe)
Java NIO 管道是2个线程之间的单向数据连接.Pipe有一个source通道和一个sink通道.数据会被写到sink通道,从source通道读取. 代码使用示例: public static v ...