Cf 101 Div.2
2012-02-07 19:53
253 查看
A题
出现的字符及其次数全部匹配即可。
B题
推规律,注意细节,比如中线什么的。
C题
想法题,好题。
给定n<=3000个人,排队,给定他们每个人前面严格比之高的人的个数num[i],要求你输出他们的高度(高度随意指定,但必须满足他们每个人前面严格比之高的人的个数)。
我的做法:
输入的个数从小到大排序后,第一个必须: num[1]=0, 否则输出 -1;
所有(当然包括第一个人)num[i]的人的高度指定是 5000,
比如num[]= { -1,0,0,0,2,2,3,4,5... };
开始是 5000 5000 5000
然后对于num[4]=2, 我在已经构造的序列里找第 (2+1) 个位置,并且取[ 1, 2 ]的最小值val=5000, 将val-1赋给第4个人。
==》 5000 5000 4999 5000
然后 num[5]=2,
==> 5000 5000 4999 4999 5000
然后num[6]=3,
==> 5000 5000 4999 4998 4999 5000
类推。。。我这种做法保证新插入的数比后面的数都更小,所以不会影响后面的人。
D题
看题解的,又看了他人代码。
[0,L]跑道上,有n个跨栏,n and L (0 ≤ n ≤ 105, 1 ≤ L ≤ 109).
然后是n组数据: xi, di, ti, pi (0 ≤ xi ≤ L, 1 ≤ di, ti, pi ≤ 109, xi + di ≤ L)。
xi是坐标,该人必须从xi-pi处开始作跨栏的准备,在xi处跳跃,然后飞跃di的距离,飞跃时间是ti,在地上的时间都是1s一个单位距离。使用跨栏必须是
x轴正方向。
算法是:
1、建图:
xi-pi
到 xi+di,权值: pi+ti;
对所有加入的点集合,按坐标从小到大排序,每相邻的点建立边。
同时记得还要建立反边。(必须要有反边,是这题很值得思考的地方,因为可以为了利用某个好的跨栏(飞跃时间短,距离长)而逆向跑(时间短)的情况。)
dijkstra+set即可。
map处理输入数据,建立映射的代码也很不错。
代码:
E题
神题。其实是水题,考察是经典算法理解的是否透彻,在达尔的指导下会了。
要求构造一个生成树,边的属性有s,m两种,要求所用边的属性各半。
思路:
prim算法中,每次取的是连接ST和非ST的点集合的具有最小权值的边,而在这里要变换取属性了。比如对于取非集合的点,如果有某个点,具有s的边到ST同时又具有m的边的ST,那么优先考虑取。否则随意取s,m
具体看代码,很值得反复思考的一个题目。
出现的字符及其次数全部匹配即可。
B题
推规律,注意细节,比如中线什么的。
C题
想法题,好题。
给定n<=3000个人,排队,给定他们每个人前面严格比之高的人的个数num[i],要求你输出他们的高度(高度随意指定,但必须满足他们每个人前面严格比之高的人的个数)。
我的做法:
输入的个数从小到大排序后,第一个必须: num[1]=0, 否则输出 -1;
所有(当然包括第一个人)num[i]的人的高度指定是 5000,
比如num[]= { -1,0,0,0,2,2,3,4,5... };
开始是 5000 5000 5000
然后对于num[4]=2, 我在已经构造的序列里找第 (2+1) 个位置,并且取[ 1, 2 ]的最小值val=5000, 将val-1赋给第4个人。
==》 5000 5000 4999 5000
然后 num[5]=2,
==> 5000 5000 4999 4999 5000
然后num[6]=3,
==> 5000 5000 4999 4998 4999 5000
类推。。。我这种做法保证新插入的数比后面的数都更小,所以不会影响后面的人。
D题
看题解的,又看了他人代码。
[0,L]跑道上,有n个跨栏,n and L (0 ≤ n ≤ 105, 1 ≤ L ≤ 109).
然后是n组数据: xi, di, ti, pi (0 ≤ xi ≤ L, 1 ≤ di, ti, pi ≤ 109, xi + di ≤ L)。
xi是坐标,该人必须从xi-pi处开始作跨栏的准备,在xi处跳跃,然后飞跃di的距离,飞跃时间是ti,在地上的时间都是1s一个单位距离。使用跨栏必须是
x轴正方向。
算法是:
1、建图:
xi-pi
到 xi+di,权值: pi+ti;
对所有加入的点集合,按坐标从小到大排序,每相邻的点建立边。
同时记得还要建立反边。(必须要有反边,是这题很值得思考的地方,因为可以为了利用某个好的跨栏(飞跃时间短,距离长)而逆向跑(时间短)的情况。)
dijkstra+set即可。
map处理输入数据,建立映射的代码也很不错。
代码:
/*Feb 3, 2012 5:54:16 PM yimao D-Take-off Ramps GNU C++ Accepted 530ms 23800KB*/ #include <cstdio> #include <cstring> #include <cmath> #include <iostream> #include <algorithm> #include <set> #include <map> using namespace std; #define MM(a,b) memset(a,b,sizeof(a)); typedef unsigned long long u64; typedef long long lld; const int maxint= 2000000000; #define maxn 200100 int n,L,top; struct Edge{ int u,v,w,id; Edge *next; }*adj[maxn], edge[maxn*3]; void Add_edge(int u,int v,int w,int id){ Edge *ptr= &edge[++top]; ptr->u= u; ptr->v= v; ptr->w= w; ptr->id= id; ptr->next= adj[u]; adj[u]= ptr; } int cnt; map<int,int>mm; int dis[maxn],Index[maxn],pre[maxn]; bool use[maxn]; struct cmp{ bool operator()(int i,int j)const{ return dis[i]<dis[j] || (dis[i]==dis[j]&&i<j); } }; set<int,cmp>Q; void Dijkstra(int st,int N){ for(int i=1;i<=N;++i) dis[i]= maxint, use[i]=0; dis[st]=0; if( !Q.empty() ) Q.clear(); Q.insert( st ); while( !Q.empty() ){ int u= *Q.begin(); Q.erase(u); use[u]= 1; if( u==2 ) return; // L-->2,improve speed; for( Edge *ptr= adj[u]; ptr; ptr= ptr->next ){ int v= ptr->v; if( use[v]==0 && dis[v]>dis[u]+ ptr->w ){ Q.erase( v ); dis[v]= dis[u]+ ptr->w; Q.insert( v ); pre[v]= u; Index[v]= ptr->id; } } } } int node[maxn]; int main() { //freopen("D.txt","r",stdin); int i,x,d,t,p; while(cin>>n>>L){ top=0; MM( adj, 0 ); cnt=0; if( !mm.empty() ) mm.clear(); mm[0]= ++cnt, mm[L]= ++cnt; for(i=1;i<=n;++i){ scanf("%d%d%d%d",&x,&d,&t,&p); if( x-p<0 ) continue; if( mm.find(x-p)==mm.end() ) mm[x-p]= ++cnt; if( mm.find(x+d)==mm.end() ) mm[x+d]= ++cnt; Add_edge( mm[x-p], mm[x+d], p+t, i ); } map<int,int>::iterator it1,it2; for(it1= mm.begin();;++it1){ it2= it1; if( (++it2)==mm.end() ) break; Add_edge( it1->second, it2->second, it2->first - it1->first, 0 ); Add_edge( it2->second, it1->second, it2->first - it1->first, 0 ); ////// } Dijkstra(1,cnt); printf("%d\n", dis[2]); int u= 2, c=0; while(u!=1){ if( Index[u]!=0 ) node[++c]= Index[u]; u= pre[u]; //printf("%d ",u); } printf("%d\n",c); for(i=c;i>0;--i){ printf("%d%c",node[i], i==1 ? '\n' : ' '); } } }
E题
神题。其实是水题,考察是经典算法理解的是否透彻,在达尔的指导下会了。
要求构造一个生成树,边的属性有s,m两种,要求所用边的属性各半。
思路:
prim算法中,每次取的是连接ST和非ST的点集合的具有最小权值的边,而在这里要变换取属性了。比如对于取非集合的点,如果有某个点,具有s的边到ST同时又具有m的边的ST,那么优先考虑取。否则随意取s,m
具体看代码,很值得反复思考的一个题目。
相关文章推荐
- Cf 98 Div.2
- CF 334 div.2-C/div.1-A/603A Alternative Thinking
- 【数论】CF#364 div.2 B.Cells Not Under Attack
- CF_#322(Div.2) D. Three Logos(greedy)
- Cf 103 div.2
- cf Round #202 (div.2) C ------------ Mafia
- CF round#439 div.2 C The Intriguing Obsession【DP】
- CF-448(Div.2)-A. Pizza Separation
- CF 335 div.2-C/div.1-A/605A Sorting Railway Cars
- CF_318_Div.2 Bear and Elections(二分||暴力枚举)
- Cf 104 div.2
- CF Round #354 Div.2
- cf 267 div.2 D Fedor and Essay
- Cf 102 Div.2
- Cf 97 Div.2
- CF round#420 div.2 E Okabe and El Psy Kongroo【矩阵快速幂】
- 【CF】Codeforces Round #466 (Div.2)
- CF 335 div.2-A/606A Magic Spheres(读错题意系列)
- CF 335 div.1-B/div.2-D/605 B Lazy Student
- CF_#324(Div.2)