小明系列问题——小明序列
Time Limit: 3000/1000 MS (Java/Others) Memory Limit: 65535/32768 K (Java/Others)Total Submission(s): 925 Accepted Submission(s): 224
Problem Description
大家都知道小明最喜欢研究跟序列有关的问题了,可是也就因为这样,小明几乎已经玩遍各种序列问题了。可怜的小明苦苦地在各大网站上寻找着新的序列问题,可是找来找去都是自己早已研究过的序列。小明想既然找不到,那就自己来发明一个新的序列问题吧!小明想啊想,终于想出了一个新的序列问题,他欣喜若狂,因为是自己想出来的,于是将其新序列问题命名为“小明序列”。
提起小明序列,他给出的定义是这样的:
①首先定义S为一个有序序列,S={ A1 , A2 , A3 , ... , An },n为元素个数 ;
②然后定义Sub为S中取出的一个子序列,Sub={ Ai1 , Ai2 , Ai3 , ... , Aim },m为元素个数 ;
③其中Sub满足 Ai1 < Ai2 < Ai3 < ... < Aij-1 < Aij < Aij+1 < ... < Aim ;
④同时Sub满足对于任意相连的两个Aij-1与Aij都有 ij - ij-1 > d (1 < j <= m, d为给定的整数);
⑤显然满足这样的Sub子序列会有许许多多,而在取出的这些子序列Sub中,元素个数最多的称为“小明序列”(即m最大的一个Sub子序列)。
例如:序列S={2,1,3,4} ,其中d=1;
可得“小明序列”的m=2。即Sub={2,3}或者{2,4}或者{1,4}都是“小明序列”。
当小明发明了“小明序列”那一刻,情绪非常激动,以至于头脑凌乱,于是他想请你来帮他算算在给定的S序列以及整数d的情况下,“小明序列”中的元素需要多少个呢?
提起小明序列,他给出的定义是这样的:
①首先定义S为一个有序序列,S={ A1 , A2 , A3 , ... , An },n为元素个数 ;
②然后定义Sub为S中取出的一个子序列,Sub={ Ai1 , Ai2 , Ai3 , ... , Aim },m为元素个数 ;
③其中Sub满足 Ai1 < Ai2 < Ai3 < ... < Aij-1 < Aij < Aij+1 < ... < Aim ;
④同时Sub满足对于任意相连的两个Aij-1与Aij都有 ij - ij-1 > d (1 < j <= m, d为给定的整数);
⑤显然满足这样的Sub子序列会有许许多多,而在取出的这些子序列Sub中,元素个数最多的称为“小明序列”(即m最大的一个Sub子序列)。
例如:序列S={2,1,3,4} ,其中d=1;
可得“小明序列”的m=2。即Sub={2,3}或者{2,4}或者{1,4}都是“小明序列”。
当小明发明了“小明序列”那一刻,情绪非常激动,以至于头脑凌乱,于是他想请你来帮他算算在给定的S序列以及整数d的情况下,“小明序列”中的元素需要多少个呢?
Input
输入数据多组,处理到文件结束;
输入的第一行为两个正整数 n 和 d;(1<=n<=10^5 , 0<=d<=10^5)
输入的第二行为n个整数A1 , A2 , A3 , ... , An,表示S序列的n个元素。(0<=Ai<=10^5)
输入的第一行为两个正整数 n 和 d;(1<=n<=10^5 , 0<=d<=10^5)
输入的第二行为n个整数A1 , A2 , A3 , ... , An,表示S序列的n个元素。(0<=Ai<=10^5)
Output
请对每组数据输出“小明序列”中的元素需要多少个,每组测试数据输出一行。
Sample Input
2 0 1 2 5 1 3 4 5 1 2 5 2 3 4 5 1 2
Sample Output
2 2 1//LIS变体,直接dp行不通,线段树o(nlogn)时间解决#include<iostream> #include<string> #include<vector> #include<list> #include<set> #include<map> #include<algorithm> #include<cstdio> #include<cstdlib> #include<cstring> #include<cmath> using namespace std; #define LTREE_N 100030 class Ltree { public: int val[LTREE_N<<2]; int build(int pos, int start, int end) { if(start==end){ scanf("%d",&val[pos]); return val[pos]; } int mid = (start+end)>>1; int lvalue = build(pos<<1,start,mid), rvalue = build((pos<<1)|1,mid+1,end); return val[pos] = max(lvalue,rvalue); } int query(int pos, int start, int end, int left, int right) { if(left>right) return 0; if(start==left&&end==right) return val[pos]; int mid = (start+end)>>1; if(right<=mid) return query(pos<<1,start,mid,left,right); if(left>mid) return query((pos<<1)|1,mid+1,end,left,right); return max(query(pos<<1,start,mid,left,mid), query((pos<<1)|1,mid+1,end,mid+1,right)); } int update(int pos,int start, int end, int x, int value) { if(start==x&&end==x){ val[pos]=value; return value;} int mid = (start+end)>>1; if(x<=mid) update(pos<<1,start,mid,x,value); else update((pos<<1)|1,mid+1,end,x,value); return val[pos] = max(val[pos<<1], val[(pos<<1)|1]); } }; Ltree lt; struct node { int po; int num; }a[LTREE_N]; bool cmp(node a,node b) { if(a.num==b.num) return a.po>b.po; return a.num<b.num; } int main() { int n,d; while(scanf("%d%d",&n,&d)!=EOF) { int i; memset(lt.val,0,sizeof(lt.val)); for(i=1;i<=n;i++) { scanf("%d",&a[i].num); a[i].po=i; } sort(a+1,a+n+1,cmp); for(i=1;i<=n;i++) { int po=a[i].po,tmp=lt.query(1,1,n,1,po-d-1); lt.update(1,1,n,po,tmp+1); } printf("%d\n",lt.val[1]); } return 0; }
湫湫系列故事——过年回家
Time Limit: 500/200 MS (Java/Others) Memory Limit: 65535/32768 K (Java/Others)Total Submission(s): 661 Accepted Submission(s): 140
Problem Description出门在外,最想念的还是家,对在深圳腾讯工作的HR湫湫来说,春节回家是一年中最期盼的事,不仅可以见到阔别已久的亲人,还能以相亲的名义调侃众多帅哥(她的内心告诉她:如果相亲能遇到参加过腾讯编程马拉松的同学,就直接把自己嫁了~)。 同时,每年的春节湫秋也都会纠结一把,因为车票实在是太难抢了,不过2013的春节有点特殊,作为一个曾经的ACMer,湫湫制作出了很完美的刷票机,也就是说她再也不用担心买不上票了,但是想来想去还是觉得随便买票实在是浪费了辛辛苦苦搞出来的刷票机,所以她决定要用最舒适的方式回家。 假设湫湫有可能经过的n个城市分别编号从1到n,湫湫要从城市A回到城市B,购票网站上列出了t辆列车行程,每辆车的行程用一个字符串表示,途径的城市间用+号相连,如1+2+3+5代表一辆从1城市分别经过2,3到达5的火车,湫湫可以从中间任意一站出发和下车(路径是单向的,即必须沿字符串从左到右来走),每个字符串对应着一个整数k,k=0表示该车只有硬座,k=1表示该车有卧铺也有硬座,在整个回家的计划中,同一辆车可以坐无限次,为了中途换车的方便,如果在起点坐的是卧铺,则后面乘坐的车必须全是卧铺,同样的,如果在起点坐的是硬座,则后面乘坐的车必须全是硬座,假设一段(一辆车行程中,两相邻城市间为一段)硬座的不舒适度是D1,一段卧铺的不舒适度是D2,求湫湫回家最小的不舒适度。
Input输入数据的第一行包含一个整数Q,表示测试数据的组数; 每组数据的第一行是2个正整数n和t,分别表示城市数和列车数; 接下来t行,每行一个字符串表示列车行程,字符串长度小于10000,每个字符串后跟一个整数k(k为0或1),之间用空格隔开; 接下来一行是D1,D2,其含义见题目描述; 最后一行是2个正整数A和B,表示起始和终点城市。 [Technical Specification] 1 <= Q <= 100 1 < n <= 200 1 < t <= 1000 0 < D1 <= 10000, 0 < D2 <= 10000,D1和D2的大小关系不确定 1 <= A, B <= n 且 A <> B
Output对于每组数据,如果湫湫可以到达目的地,则输出一个整数,表示湫湫到家所需的最小不舒适度。如果不能到达则直接输出-1。
Sample Input1 6 5 2+4+3+5+1+6 1 5+4+2+3+1 1 3+2+5+1+6 1 6+2 0 6+3+1+4+5+2 0 3 2 5 3
Sample Output4
//边权值相等的最短路径,BFS解决#include<iostream> #include<string> #include<vector> #include<list> #include<stack> #include<queue> #include<set> #include<map> #include<algorithm> #include<cstdio> #include<cstdlib> #include<cstring> #include<cmath> using namespace std; #define Gpraph_VERTEX_MAX 201 struct LNode { int node; int pathVal; LNode(int a,int b):node(a),pathVal(b){} }; struct Node { bool visited; int depth; list<LNode> linkNodes; Node():visited(false){} }; class Graph { public: vector<Node> gp; int pval; Graph(int size):gp(size){} void AddPath(int start, int end, int pathval=0) { gp[start].linkNodes.push_back(LNode(end,pathval)); } int FindMinPath(int start, int end)//等权值,深搜 { queue<int> nodes; gp[start].visited=true; gp[start].depth=0; nodes.push(start); while(!nodes.empty()) { int now = nodes.front(); nodes.pop(); int depth=gp[now].depth; for(list<LNode>::iterator it=gp[now].linkNodes.begin();it!=gp[now].linkNodes.end();it++) { if(it->node == end) {return (int)pval*(depth+1); } if(!(gp[it->node].visited)) { gp[it->node].visited = true; gp[it->node].depth = depth+1; nodes.push(it->node); } } } return -1; } }; int a[201]; int main() { int q,n,t; scanf("%d",&q); while(q--) { scanf("%d%d",&n,&t); Graph g1(n+1),g2(n+1); while(t--) { scanf("%d",&a[1]); int i; for(i=2;getchar()=='+';i++) scanf("%d",&a[i]); scanf("%d",&a[0]); if(a[0]==0) for(int j=1;j<i-1;j++) g1.AddPath(a[j],a[j+1]); else for(int j=1;j<i-1;j++) { g1.AddPath(a[j],a[j+1]);g2.AddPath(a[j],a[j+1]);} } scanf("%d%d",&a[0],&a[1]); g1.pval=a[0]; g2.pval=a[1]; scanf("%d%d",&a[0],&a[1]); int path1 = g1.FindMinPath(a[0],a[1]), path2 = g2.FindMinPath(a[0],a[1]); if(path1==-1||path2==-1) printf("%d\n",max(path1,path2)); else printf("%d\n",min(path1,path2)); } return 0; }
威威猫系列故事——过生日
Time Limit: 500/200 MS (Java/Others) Memory Limit: 65535/32768 K (Java/Others) Total Submission(s): 892 Accepted Submission(s): 235
Problem Description
2月29号是威威猫的生日,由于这个日子非常特殊,4年才一次,所以生日这天许多朋友都前往威威猫家祝贺他的生日。 大家给威威猫买了一个非常大非常大的蛋糕,蛋糕的形状是一个有n条边的凸多边形,可是威威猫的审美观有一点奇怪,他只喜欢有m条边的蛋糕,所以他要伙伴们把这个蛋糕切p次,然后给他一个只有m条边的新蛋糕。这下大家急了,这不是坑爹吗,审美观崎岖作怪。 假设蛋糕可看成一个平面含n条边的凸多边形,每一刀必须沿直线切下去,p刀之后能给威威猫切出一个m条边的蛋糕吗?
Input
多组测试数据,每组占一行,包含3个整数n, m, p(含义如上)。
[Technical Specification] 3 <= n <= 10^100 0 < m <= 10^100 0 <= p <= 10^100
Output
每组测试数据,如果能够切出威威猫喜欢的蛋糕,请输出"YES",否则请输出"NO";每组数据输出一行。
Sample Input
4 5 1
Sample Output
YES
//大数 直接用原先冗长的大数模板
#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<algorithm>
#include<cstdlib>
using namespace std;
class BigNum
{
friend istream& operator >> (istream&, BigNum&);
friend ostream& operator << (ostream&, BigNum&);
string big;
int flag;
void trans()
{
if(big[0] == '-') { big = string(big.begin()+1,big.end()); flag=-1;}
else { flag = 1; }
for(int i=0, j=big.size()-1;i<j;i++,j--)
swap(big[i],big[j]);
for(int i=0;i<big.size();i++)
big[i] -= '0';
}
public:
enum{NUM_LEN=200};
BigNum()
{
}
BigNum(string a)
{
big = a;
trans();
}
BigNum(int i)
{
char buf[NUM_LEN];
sprintf(buf,"%d",i);
big = buf;
trans();
}
bool GetNum(istream &cin)
{
if( cin>>big ){ trans(); return true; }
else {return false;}
}
void PrintBig()
{
if(flag<0) cout<<'-';
for(int i=big.size()-1;i>=0;i--)
cout<<char('0'+big[i]);
cout<<endl;
}
BigNum AbsNum()
{
BigNum rlt(*this);
rlt.flag=1;
return rlt;
}
BigNum operator + (BigNum a)
{
BigNum rlt;
if(flag == a.flag)
{
int cf=0;
rlt.flag=flag;
for(int i=0;i<big.size()||i<a.big.size();i++)
{
rlt.big.push_back(cf + (i<big.size()?big[i]:0) + (i<a.big.size()?a.big[i]:0) );
if(rlt.big[i]>=10) {cf = rlt.big[i]/10; rlt.big[i]%=10; }
else {cf=0;}
}
if(cf >0){ rlt.big.push_back(cf);}
return rlt;
}
BigNum tmp1=AbsNum(),tmp2=a.AbsNum();
if(tmp1==tmp2){ return BigNum(0); }
if(tmp1>tmp2) { rlt = tmp1-tmp2; rlt.flag=flag; return rlt; }
if(tmp1<tmp2) { rlt = tmp2-tmp1; rlt.flag=a.flag; return rlt; }
}
BigNum operator - (BigNum a)
{
BigNum rlt;
if(flag != a.flag)
{
rlt = AbsNum() + a.AbsNum();
rlt.flag = flag;
return rlt;
}
BigNum tmp1=AbsNum(),tmp2=a.AbsNum();
if(tmp1==tmp2){ return BigNum(0);}
int tag=flag;
if(tmp1<tmp2) { swap(tmp1,tmp2); tag=(flag==1?-1:1); }
if(tmp1>tmp2)
{
int cf=0;
for(int i=0;i<tmp1.big.size()||i<tmp2.big.size();i++)
{
int rlttmp = int(i<tmp1.big.size()?tmp1.big[i]:0) - int(i<tmp2.big.size()?tmp2.big[i]:0) - cf;
if(rlttmp<0) {cf = (abs(rlttmp)-1)/10+1; rlttmp+=cf*10; }
else {cf=0;}
rlt.big.push_back((char)rlttmp);
}
}
for(int i=rlt.big.size()-1;i>=0;i--)
if(rlt.big[i]!=0)
{
rlt.big = string(rlt.big.begin(),rlt.big.begin()+i+1);
break;
}
rlt.flag = tag;
return rlt;
}
bool IsZero()
{
return big.size()==1 && big[0]==0;
}
bool operator == (BigNum a)
{
return big == a.big && flag == a.flag;
}
bool operator != (BigNum a)
{
return !(*this==a);
}
bool operator > (BigNum a)
{
if(flag>a.flag) return true;
else if(a.flag>flag) return false;
if(big.size() > a.big.size()) return true;
else if(a.big.size()>big.size()) return false;
for(int i=big.size()-1;i>=0;i--)
{
if(big[i]>a.big[i]) return true;
else if(a.big[i]>big[i]) return false;
}
return false;
}
bool operator < (BigNum a)
{
if(flag>a.flag) return false;
else if(a.flag>flag) return true;
if(big.size() > a.big.size()) return false;
else if(a.big.size()>big.size()) return true;
for(int i=big.size()-1;i>=0;i--)
{
if(big[i]>a.big[i]) return false;
else if(a.big[i]>big[i]) return true;
}
return false;
}
bool operator >= (BigNum a)
{
return !(*this<a);
}
bool operator <= (BigNum a)
{
return !(*this>a);
}
};
istream& operator >> (istream& cin, BigNum &a)
{
istream &in = cin>>a.big;
a.trans();
return in;
}
ostream& operator << (ostream& cout, BigNum &a) //没有传递错误
{
a.PrintBig();
return cout;
}
int main()
{
BigNum n,m,p;
while( cin>>n>>m>>p )
{
if( m < 3 )
{
cout<<"NO"<<endl;
continue;
}
if( n>m && p!=0 )
{ cout<<"YES"<<endl;
continue;
}
if( n<m && n+p>=m )
{
cout<<"YES"<<endl;
continue;
}
if( m==n )
{
cout<<"YES"<<endl;
continue;
}
cout<<"NO"<<endl;
}
return 0;
}