目录
显示
一份咕咕了两个月的题解?(其实有两道题的题解都在洛谷上发布了)
A. Convention
题目链接
https://www.luogu.org/problem/P5119
题解
本题可以采用二分答案的方法解决。
先将牛到达的时间排序,然后二分最长等待时间即可。
#include <cstdio> #include <algorithm> using namespace std; int a[100005]; int main() { //freopen("convention.in","r",stdin); //freopen("convention.out","w",stdout); int n,m,c; scanf("%d%d%d",&n,&m,&c); for(int i=1;i<=n;i++) scanf("%d",&a[i]); sort(a+1,a+n+1); int l=0,r=a[n]-a[1]; while(l<r) { int mid=(l+r)>>1,cnt=1,sta=1; for(int i=1;i<=n;i++) if(a[i]-a[sta]>mid||i-sta+1>c) //如果等待时间超过了二分中点mid或当前车辆已经满载,就重新发一辆车 { cnt++; sta=i; } if(cnt<=m)r=mid;//该时间下车辆数充足,等待时间可以更小 else l=mid+1;//车辆不足,等待时间要更长 } printf("%d\n",l); fclose(stdin); fclose(stdout); return 0; }
B. Convention II
题目链接
https://www.luogu.org/problem/P5120
题解
一道很暴力的模拟题。
采用优先队列维护等待序列,每次让等待队列的堆顶出队,并计算答案。
(代码量还不小)
#include <cstdio> #include <iostream> #include <algorithm> #include <iterator> #include <vector> #include <queue> #include <map> using namespace std; struct node { long long id,a,t; bool operator<(const node&a)const { return a.id<id; } }a[100005]; struct lian { long long t; vector<int> l; }b[100005]; priority_queue<node> q; map<int,int> ma; bool cmp(const node&a,const node&b) { return a.a<b.a||(a.a==b.a&&a.id<b.id); } int main() { long long n,ans=0; cin>>n; for(int i=1;i<=n;i++) { cin>>a[i].a>>a[i].t; a[i].id=i; } sort(a+1,a+n+1,cmp); long long x=a[1].a,cnt=1; b[1].t=x; ma[1]=x; for(int i=1;i<=n;i++) if(a[i].a==x)b[cnt].l.push_back(i); else { b[++cnt].t=a[i].a; ma[cnt]=a[i].a; b[cnt].l.push_back(i); } long long curt=a[1].a,curl=b[1].t,inque=0,pi=1; for(vector<int>::iterator it=b[1].l.begin();it!=b[1].l.end();it++) q.push(a[*it]),inque++; while(!q.empty()) { node eatc=q.top();//队首奶牛出队并计算答案 ans=max(ans,curt-eatc.a); curt+=eatc.t; q.pop(); while(ma[pi+1]<=curt&&ma[pi+1]!=0)//到达的奶牛都入队等待 { for(vector<int>::iterator it=b[++pi].l.begin();it!=b[pi].l.end();it++) q.push(a[*it]),inque++; curl=ma[pi]; if(curl==0)break; } if(q.empty()&&inque<n) { for(vector<int>::iterator it=b[++pi].l.begin();it!=b[pi].l.end();it++) q.push(a[*it]),inque++; curl=ma[pi]; curt=max(a[inque].a,curt); } } cout<<ans<<endl; return 0; }
C. Mooyo Mooyo
题目链接
https://www.luogu.org/problem/P5121
题解
怎么还是模拟…
本题是一个简单模拟题。
每次按题意 dfs 找出连通块,并将其删除即可。
注意当一个格子下面为空的时候,不要忘了把它往下移动。
#include <cstdio> #include <cstring> #include <set> using namespace std; struct node { int x,y; bool operator<(const node&a)const { return x<a.x||(x==a.x&&y<a.y); } }; set<node> se; char s[105][15]; int vis[105][15],n,k; int dfs(int x,int y,char cur)//找连通块 { vis[x][y]=1; se.insert({x,y});//将找到的格子加入集合,便于后面执行删除操作 int ans=1; if((!vis[x-1][y])&&s[x-1][y]==cur)ans+=dfs(x-1,y,cur); if((!vis[x+1][y])&&s[x+1][y]==cur)ans+=dfs(x+1,y,cur); if((!vis[x][y-1])&&s[x][y-1]==cur)ans+=dfs(x,y-1,cur); if((!vis[x][y+1])&&s[x][y+1]==cur)ans+=dfs(x,y+1,cur); return ans; } int main() { //freopen("mooyomooyo.in","r",stdin); //freopen("mooyomooyo.out","w",stdout); scanf("%d%d",&n,&k); for(int i=1;i<=n;i++) scanf("%s",s[i]+1); while(1) { memset(vis,0,sizeof(vis)); bool flag=false; for(int i=1;i<=n;i++) for(int j=1;j<=10;j++) if((!vis[i][j])&&s[i][j]!='0') { int cnt=dfs(i,j,s[i][j]); if(cnt>=k) { for(set<node>::iterator it=se.begin();it!=se.end();it++) s[(*it).x][(*it).y]='0'; flag=true; } se.clear(); } for(int i=n-1;i>=1;i--)//模拟下落过程 for(int j=1;j<=10;j++) { if(s[i][j]=='0')continue; int x=i,y=j; while(s[x+1][y]=='0') swap(s[x][y],s[x+1][y]),x++; } if(!flag)break; } for(int i=1;i<=n;i++) puts(s[i]+1); return 0; }