【ACUMTB团队赛】第一周题解
周赛地址:https://vjudge.net/contest/152769#overview
A题:
题意:Nikita想选择两门课A和B,使得他想要选的所有学位能被这两门课划分成4个集合,分别是:有AB,有B没A,有A没B,没AB的,并求出这些集合的最大值的最小值。
思路:xjb模拟,才1e6的操作量……
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 5 using namespace std; 6 7 const int maxn=105; 8 9 int mp[maxn][maxn]; 10 11 int main() 12 { 13 int mx=0x7fffffff; 14 int n,m; 15 scanf("%d %d",&n,&m); 16 for(int i=1;i<=n;i++){ 17 for(int j=1;j<=m;j++){ 18 scanf("%d",&mp[i][j]); 19 } 20 } 21 int u=0,v=0; 22 for(int i=1;i<=m;i++){ 23 for(int j=i+1;j<=m;j++){ 24 int a=0,b=0,c=0,d=0; 25 for(int k=1;k<=n;k++){ 26 if(mp[k][j]==0&&mp[k][j]==mp[k][i]) a++; 27 else if(mp[k][j]==1&&mp[k][j]==mp[k][i]) b++; 28 else if(mp[k][j]==0&&mp[k][i]==1) c++; 29 else if(mp[k][j]==1&&mp[k][i]==0) d++; 30 } 31 int tem=max(a,max(b,max(c,d))); 32 if(mx>tem){ 33 mx=tem; 34 u=i,v=j; 35 } 36 } 37 } 38 printf("%d\n",mx); 39 printf("%d %d",u,v); 40 return 0; 41 }
B题:
题意:给出起始天和结束天,每ki天(i=2,3……)会作报告,作报告的天会被去掉,剩下的天按照k递增的顺序作报告,问剩下的天数为多少。
思路:按要求玩就行,不理解的话用vector模拟一下就行。
1 #include<iostream> 2 using namespace std; 3 int main() 4 { 5 int l,r,i=2; 6 cin>>l>>r; 7 while(r/i) 8 { 9 r=r-r/i; 10 i++; 11 } 12 i=2; 13 l--; 14 while(l/i) 15 { 16 l=l-l/i; 17 i++; 18 } 19 cout<<r-l<<endl; 20 return 0; 21 }
C题:
题意:n点m边的无向图,求1到n的次短路(最短路可能不止一条,但次短路必须是小于最短路的那条)。
思路:次短路的求法:到v点的最短路记为d[0][v],次短路记为d[1][v],按照Dijkstra的方法进行松弛,①如果d[0][v]>d[now.pos][now.t]+now.w,则先更新d[1][v]=d[0][v],再执行松弛操作,并且将两点的状态放入优先队列中。②如果d[1][v]>d[now.pos][now.t]+now.w,则进行松弛操作,将点的状态放入优先队列中。
由于此题最短路不唯一,在进行②时需要判断v是否为n且d[0][v]==d[now.pos][now.t]+now.w,如果成立则不进行松弛。
1 #include <iostream> 2 #include <cstdio> 3 #include <queue> 4 #include <cstring> 5 #include <vector> 6 #include <functional> 7 8 using namespace std; 9 10 const int maxn=5005; 11 const int inf=1e9; 12 13 typedef pair<int,int> P; 14 15 vector<P> G[maxn]; 16 17 struct node{ 18 int t,v,pos; 19 bool operator <(const node&a)const{ 20 return v>a.v; 21 } 22 }; 23 24 int n,m; 25 26 int d[2][maxn]; 27 int cou[2][maxn]; 28 29 void init(){ 30 for(int i=0;i<maxn;i++){ 31 G[i].clear(); 32 d[0][i]=d[1][i]=inf; 33 } 34 } 35 36 void dijkstra(int s){ 37 priority_queue<node> q; 38 q.push((node){s,0,0}); 39 d[0][s]=0; 40 while(!q.empty()){ 41 node now=q.top(); 42 q.pop(); 43 for(int i=0;i<G[now.t].size();i++){ 44 int v=G[now.t][i].first; 45 int dis=G[now.t][i].second; 46 if(d[0][v]>d[now.pos][now.t]+dis){ 47 d[1][v]=d[0][v]; 48 d[0][v]=d[now.pos][now.t]+dis; 49 q.push((node){v,d[1][v],1}); 50 q.push((node){v,d[0][v],0}); 51 } 52 else if(d[1][v]>d[now.pos][now.t]+dis){ 53 if(v==n&&d[0][v]==d[now.pos][now.t]+dis) continue; 54 d[1][v]=d[now.pos][now.t]+dis; 55 q.push((node){v,d[1][v],1}); 56 } 57 } 58 } 59 } 60 61 int main(){ 62 ios::sync_with_stdio(false); 63 cin.tie(0); 64 int T; 65 cin>>T; 66 int cou=0; 67 while(T--){ 68 init(); 69 cin>>n>>m; 70 for(int i=0;i<m;i++){ 71 int s,t,e; 72 cin>>s>>t>>e; 73 G[s].push_back(P(t,e)); 74 G[t].push_back(P(s,e)); 75 } 76 dijkstra(1); 77 cout<<"Case "<<++cou<<": "<<d[1][n]<<endl; 78 } 79 return 0; 80 }
D题:
题意:在规定时间内,保证唱最多的歌的情况下,时间唱到最长(所有歌的时间<180s,劲歌金曲678s)
思路:01背包变形,dp[i]为唱时间<=i的歌的数目,最后遍历一遍找最大的dp[i],i为时间的最大值,记得留1s给劲歌金曲。
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cmath> 5 6 using namespace std; 7 8 const int maxn=11000; 9 const int maxs=55; 10 11 int dp[maxn]; 12 int a[maxs]; 13 14 int main(){ 15 int T,cou=0; 16 cin>>T; 17 while(T--){ 18 int n,t; 19 cin>>n>>t; 20 memset(dp,-1,sizeof(dp)); 21 for(int i=1;i<=n;i++){ 22 cin>>a[i]; 23 } 24 dp[0]=0; 25 for(int i=1;i<=n;i++){ 26 for(int j=t-1;j>=a[i];j--){ 27 dp[j]=max(dp[j],dp[j-a[i]]+1); 28 } 29 } 30 int ans=t-1; 31 for(int i=t-1;i>=0;i--) if(dp[i]>dp[ans]) ans=i; 32 cout<<"Case "<<++cou<<": "<<dp[ans]+1<<" "<<ans+678<<endl; 33 } 34 return 0; 35 }
E题:
题意:给你n个数m组操作,每组操作有两种:1 x 将1到x的数变为升序排列,2 x 将1到x数变为降序排列,求最后的序列。
思路:单调栈。对于操作i,j(1<=i<j),当xj>xi时,在xi<s<xj的部分,j操作不被影响,1<s<xi的部分,i操作被替换成j操作,所以建立一个单调递减栈,从前向后遍历,最后一组操作单独执行。
1 #include <iostream> 2 #include <algorithm> 3 #include <cstring> 4 5 using namespace std; 6 7 const int maxn=2e5+10; 8 9 typedef pair<int,int> P; 10 11 P Stack[maxn]; 12 13 int a[maxn],soa[maxn],ans[maxn]; 14 15 int main(){ 16 ios::sync_with_stdio(false); 17 cin.tie(0); 18 int n,m; 19 cin>>n>>m; 20 for(int i=1;i<=n;i++){ 21 cin>>a[i]; 22 soa[i]=a[i]; 23 } 24 int p=0; 25 for(int i=0;i<m;i++){ 26 int opt,v; 27 cin>>opt>>v; 28 while(p&&Stack[p-1].second<v){ 29 p--; 30 } 31 Stack[p++]=P(opt,v); 32 } 33 int st=1,ed=Stack[0].second; 34 sort(soa+1,soa+ed+1); 35 for(int i=n;i>ed;i--){ 36 ans[i]=a[i]; 37 } 38 for(int i=0;i<p-1;i++){ 39 for(int j=Stack[i].second;j>Stack[i+1].second;j--){ 40 ans[j]=Stack[i].first==1?soa[ed--]:soa[st++]; 41 } 42 } 43 for(int i=Stack[p-1].second;i>=1;i--){ 44 ans[i]=Stack[p-1].first==1?soa[ed--]:soa[st++]; 45 } 46 for(int i=1;i<=n;i++){ 47 cout<<ans[i]<<" "; 48 } 49 return 0; 50 }