Codeforces Round #101 (Div. 2)
--------------
A. Amusing Joke
--
前两行的字母恰好组成最后一行
--
#include <iostream> #include <cstring> using namespace std; char a[1111]; int ch[26]={0}; int main() { cin>>a; for (int i=0;a[i];i++){ ch[a[i]-'A']++; } cin>>a; for (int i=0;a[i];i++){ ch[a[i]-'A']++; } cin>>a; for (int i=0;a[i];i++){ ch[a[i]-'A']--; } bool flag=true; for (int i=0;i<26;i++){ if (ch[i]!=0){ cout<<"NO"<<endl; flag=false; break; } } if (flag) cout<<"YES"<<endl; return 0; }-------------
B. Hopscotch
----
模拟计算(x,y)所在的格子
公式易推,注意边界
----
#include <iostream> #include <cstring> using namespace std; void solve(int a,int x,int y){ if (y%a==0){ cout<<-1<<endl; return; } int fl=y/a; if (fl==0){ if (2*x<a&&2*x>-a) cout<<1<<endl; else cout<<-1<<endl; return; } int nu=(fl+1)/2; if (fl%2==1){ if (2*x<a&&2*x>-a) cout<<nu*3-1<<endl; else cout<<-1<<endl; return; } else{ if (x>0&&x<a) cout<<nu*3+1<<endl; else if (x<0&&x>-a) cout<<nu*3<<endl; else cout<<-1<<endl; return; } } int main() { int a,x,y; cin>>a>>x>>y; solve(a,x,y); return 0; }
--------------
C. Queue
---
有n个人排成一队
给出每个人前面比他高的人数
构造一个身高序列
---
#include <iostream> #include <cstring> #include <cstdio> #include <algorithm> using namespace std; const int INF=0x3f3f3f; const int MAXN=10000; struct Data{ string name; int a; int h; }f[MAXN]; bool cmp(Data x,Data y){ return x.a<y.a; } int n,m; int main() { cin>>n; for (int i=0;i<n;i++){ cin>>f[i].name>>f[i].a; } sort(f,f+n,cmp); for (int i=0;i<n;i++){ if (f[i].a>i){ cout<<-1<<endl; return 0; } } m=0; for (int i=0;i<n;i++){ f[i].h=i+1-f[i].a; for (int j=0;j<i;j++){ if (f[j].h>=f[i].h) f[j].h++; } } for (int i=0;i<n;i++){ cout<<f[i].name<<" "<<f[i].h<<endl; } return 0; }
--------------
D. Take-off Ramps
----
长度为L的场地里有n个跳板
对位于坐标Xi的跳板,要提前Pi米准备,跳到Di用时Ti。
问从0到L的最短距离。
----
以0、L、Xi-Pi、Xi+Di为顶点构造图。
从0到L的最短路即为所求。
将每个顶点按坐标排序,相邻两个顶点之间建一条长度为两点距离差绝对值的边
跳板两端点间建一条长度为Pi+Ti的边。
距离有可能超过int。
注意输出格式以及时间效率。
--------------
#include <iostream> #include <cstring> #include <algorithm> #include <queue> #include <vector> #include <map> #include <cstdio> using namespace std; typedef long long LL; const long long INF=1LL << 60; const int maxn=500000; const int maxm=5000000; struct EdgeNode{ int to; LL w; int next; };/*==============================================*\ | Dijkstra+堆优化 | INIT: init(n);addedge(u,v,c);节点编号0~n | CALL: dijkstra(int s);dis[]:最短路;pre[]:前驱 \*==============================================*/ struct HeapNode{ LL d; int u; HeapNode(){} HeapNode(LL a,int b):d(a),u(b){} bool operator<(const HeapNode& rhs) const{ return d>rhs.d; } }; struct Dijkstra{ EdgeNode edges[maxm]; int head[maxn]; int edge,n; void init(int n){ this->n=n; memset(head,-1,sizeof(head)); edge=0; } void addedge(int u,int v,LL c){ edges[edge].w=c,edges[edge].to=v,edges[edge].next=head[u],head[u]=edge++; } bool done[maxn]; LL dis[maxn]; int pre[maxn]; void dijkstra(int s){ priority_queue<HeapNode>que; for (int i=0;i<=n;i++) dis[i]=INF; dis[s]=0; memset(done,0,sizeof(done)); que.push(HeapNode(0,s)); while (!que.empty()){ HeapNode x=que.top(); que.pop(); int u=x.u; if (done[u]) continue; done[u]=true; for (int i=head[u];i!=-1;i=edges[i].next){ int v=edges[i].to; LL w=edges[i].w; if (dis[v]>dis[u]+w){ dis[v]=dis[u]+w; pre[v]=u; que.push(HeapNode(dis[v],v)); } } } } }G; struct Data{ int x,d,t,p; int id; }a[maxn]; struct POI{ int p; int id; POI(){} POI(int a,int b):p(a),id(b){} }; vector<POI>vec; bool cmp(POI a,POI b){ return a.p<b.p; } vector<int>ans; int mp[maxn]; int main() { int n,L,m; memset(mp,-1,sizeof(mp)); scanf("%d%d",&n,&L); G.init(2*n+1); m=0; for (int i=1;i<=n;i++){ scanf("%d%d%d%d",&a[i].x,&a[i].d,&a[i].t,&a[i].p); a[i].id=i; G.addedge(i,i+n,a[i].p+a[i].t); if (a[i].t<a[i].d){ mp[i+n]=i; } //cerr<<i<<" "<<i+n<<" "<<a[i].t<<endl; vec.push_back(POI(a[i].x-a[i].p,i)); vec.push_back(POI(a[i].x+a[i].d,i+n)); } vec.push_back(POI(L,2*n+1)); vec.push_back(POI(0,0)); sort(vec.begin(),vec.end(),cmp); for (int i=0;i<(int)vec.size()-1;i++){ if (vec[i].p<0) continue; G.addedge(vec[i].id,vec[i+1].id,abs(vec[i+1].p-vec[i].p)); G.addedge(vec[i+1].id,vec[i].id,abs(vec[i].p-vec[i+1].p)); //cerr<<vec[i].id<<" "<<vec[i+1].id<<" "<<abs(vec[i+1].p-vec[i].p)<<endl; } G.dijkstra(0); printf("%I64d\n",G.dis[2*n+1]); int t=2*n+1; while (t!=0){ if (mp[t]==G.pre[t]) ans.push_back(G.pre[t]); t=G.pre[t]; } printf("%d\n",ans.size()); for (int i=(int)ans.size()-1;i>=0;i--){ printf("%d ",ans[i]); } printf("\n"); return 0; }
-------------
E. Clearing Up
--------
有n个节点的图,求最小生成树,要求S与M各占一半。
---------
易知最小生成树有n-1条边,一半为S一半为M
定义两个并查集S1、S2。答案集e1,e2。
保证属于一个集合的顶点中,任意两个顶点之间有且只有一条简单路径。
首先只考虑S边,将S边相连的顶点合并到并查集S1里的一个集合
考虑M边,若最终想要得到一个最小生成树,则并查集S1中必须只有一个集合。
所以枚举所有M边,若某M边能连接S1中不同集合的顶点,则在S1、S2中合并这两个顶点,将该M边加入答案集e1。
如果此时M边不满(n-1)/2,枚举M边,若该边能连接S2中的不同集合则合并这两个集合并将该M边加入答案集e1。
枚举所有S边,若能连接S2中不集合则合并集合并将该S边加入答案集e2。
最终答案集e1中储存的是最小生成树中的M边,e2为S边。并且size(e1)=(n-1)/2。
若size(e1)!=size(e2)则无解。
---------
#include <iostream> #include <vector> #include <cstring> #define sz(x) int(x.size()) using namespace std; const int maxn=11111; const int maxm=111111; struct DisjointSet{ int pa[maxn]; void makeSet(int n){ for (int i=0;i<=n;i++) pa[i]=i; } int findSet(int x){ if (x!=pa[x]) pa[x]=findSet(pa[x]); return pa[x]; } void unionSet(int x,int y){ x=findSet(x); y=findSet(y); if (x!=y) pa[x]=y; } }s1,s2; int n,m; struct Edge{ int u,v; char c; }; Edge vec[maxm]; vector<int> e1,e2; int d; int main() { cin>>n>>m; for (int i=0;i<m;i++){ cin>>vec[i].u>>vec[i].v>>vec[i].c; } s1.makeSet(n); s2.makeSet(n); for (int i=0;i<m;i++){ if (vec[i].c=='S'){ if (s1.findSet(vec[i].u)!=s1.findSet(vec[i].v)){ s1.unionSet(vec[i].u,vec[i].v); } } } d=(n-1)/2; for (int i=0;i<m;i++){ if (vec[i].c=='M'){ if (s1.findSet(vec[i].u)!=s1.findSet(vec[i].v)){ s1.unionSet(vec[i].u,vec[i].v); s2.unionSet(vec[i].u,vec[i].v); e1.push_back(i); d--; } } } for (int i=0;i<m;i++){ if (vec[i].c=='M'&&d>0){ if (s2.findSet(vec[i].u)!=s2.findSet(vec[i].v)){ s2.unionSet(vec[i].u,vec[i].v); e1.push_back(i); d--; } } } for (int i=0;i<m;i++){ if (vec[i].c=='S'){ if (s2.findSet(vec[i].u)!=s2.findSet(vec[i].v)){ s2.unionSet(vec[i].u,vec[i].v); e2.push_back(i); } } } d=(n-1)/2; if (sz(e1)!=d||sz(e2)!=d) cout<<-1<<endl; else{ cout<<n-1<<endl; for (int i=0;i<sz(e1);i++){ cout<<e1[i]+1<<" "; } for (int i=0;i<sz(e2);i++){ cout<<e2[i]+1<<" "; } cout<<endl; } return 0; }
---------
-