2017-2018 ACM-ICPC Latin American Regional Programming Contest GYM101889
Posted mxang
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2017-2018 ACM-ICPC Latin American Regional Programming Contest GYM101889相关的知识,希望对你有一定的参考价值。
挺有意思的一套题,题也没有啥毒瘤了,本来是队切的结果种种原因大家全挂机了。
只补了百人题,一共7个,其他的暂时先不补了,,也不会嘛qwq
H:签到
1 #include <bits/stdc++.h> 2 using namespace std; 3 int a[18],b[18]; 4 int main(){ 5 cin>>a[1]>>a[2]>>a[3]>>b[1]>>b[2]>>b[3]; 6 int ans = 0; 7 for(int i=1;i<=3;i++) 8 ans+=max(0,b[i]-a[i]); 9 cout<<ans<<endl; 10 }
C:按情况模拟一下,签到。当时队友因为这个题写炸了心态受到了影响然后我又不在((
#include <bits/stdc++.h> using namespace std; int k,n; int a[100005]; int num[100005]; vector<int> vis[100005]; int main(){ ios::sync_with_stdio(false); cin>>k>>n; int cnt = 0; int tmp = 0;//那一个超出k的数 for(int i=1;i<=n;i++){ cin>>a[i]; if(a[i]>k){ cnt++; tmp = a[i]; } else{ num[a[i]]++; } } for(int i=1;i<=k;i++){ vis[num[i]].push_back(i); } if(cnt>=2){ cout<<"*"<<endl; } else if(cnt==1){ if((n-1)%k==0&&vis[(n-1)/k].size()==k){ cout<<-tmp<<endl; } else if(n%k==0&&vis[n/k-1].size()==1&&vis[n/k].size()==k-1){// cout<<-tmp<<‘ ‘<<"+"<<vis[n/k-1][0]<<endl; } else{ cout<<"*"<<endl; } } else if(cnt==0){ if((n+1)%k==0&&vis[(n+1)/k].size()==k-1&&vis[(n+1)/k-1].size()==1){ cout<<"+"<<vis[(n+1)/k-1][0]<<endl; } else if((n-1)%k==0&&vis[(n-1)/k].size()==k-1&&vis[(n-1)/k+1].size()==1){ cout<<-vis[(n-1)/k+1][0]<<endl; } else if(n%k==0&&vis[n/k].size()==k-2&&vis[n/k+1].size()==1&&vis[n/k-1].size()==1){ cout<<-vis[n/k+1][0]<<‘ ‘<<"+"<<vis[n/k-1][0]<<endl; } else{ cout<<"*"<<endl; } } }
B:签到题
题意:给你目标字符串,你每次可以输入一个字符,输入字符为元音是会在当前串会在输入后反转,求方案数。
样例三很明显了,两边的顺序是固定的,只考虑 中间 那一部分就好。特殊情况判一下
1 #include <bits/stdc++.h> 2 using namespace std; 3 string s; 4 bool yuanyin(char a){ 5 return a==‘a‘||a==‘e‘||a==‘i‘||a==‘o‘||a==‘u‘; 6 } 7 int main(){ 8 ios::sync_with_stdio(false); 9 cin>>s; 10 int n = s.length(); 11 int odd = 0,even = 0;//我不会别的英语了 12 for(int i=0;i<n;i++){ 13 if(yuanyin(s[i])) 14 even++; 15 else 16 odd++; 17 } 18 if(even==n||odd==n){ 19 cout<<1<<endl; 20 } else{ 21 if(!yuanyin(s[0])){ 22 cout<<0<<endl; 23 } else{ 24 int tmp = 0; 25 int i=0; 26 for(;i<n;i++) { 27 if (yuanyin(s[i])) 28 tmp++; 29 if (tmp == (even + 1) / 2) { 30 break; 31 } 32 } 33 int j=i+1; 34 for(;j<n;j++){ 35 if(yuanyin(s[j])) 36 break; 37 } 38 cout<<j-i<<endl; 39 } 40 } 41 }
E:搜索题,可以利用数位dp的思想,唔数位dp我之前写过一篇博客所以这道题有了思路之后还是挺简单的。
题意:给你一个串和整数n,包含数字和‘?‘,‘?‘可以用任意数替代但不能含前导0,求能被n整除的最小串。
1 #include <bits/stdc++.h> 2 //为什么取余的运算优先级会比加减法高啊喂。。。 3 using namespace std; 4 int dp[1005][1005]; 5 string s;int n,l; 6 bool flag = false; 7 void dfs(int len,int mod,string ans){ 8 if(flag) return; 9 if(len==l){ 10 if(mod==0){ 11 cout<<ans<<endl; 12 flag = true; 13 } 14 return; 15 } 16 if(dp[len][mod]) return; 17 if(s[len]==‘?‘){ 18 for(int i=0;i<=9;i++){ 19 if(flag) return; 20 if(len==0&&i==0) continue; 21 dfs(len+1,(i+(mod*10))%n,ans+char(i+‘0‘)); 22 } 23 } else{ 24 if(flag) return; 25 dfs(len+1,(s[len]-‘0‘+mod*10)%n,ans+s[len]); 26 } 27 dp[len][mod]=1; 28 } 29 int main(){ 30 ios::sync_with_stdio(false); 31 cin>>s>>n; 32 l=s.length(); 33 dfs(0,0,""); 34 if(!flag) 35 cout<<"*"<<endl; 36 }
J:简单数学题,一个字符串,R代表能跳,P代表不能,青蛙可以从任何地方跳,求能跳回原点的步数n的方案数,n需要小于字符串长度。
很明显的gcd,然后判断一下因数就可以。
1 #include <bits/stdc++.h> 2 using namespace std; 3 int gcd(int x,int y){ 4 return y==0?x:gcd(y,x%y); 5 } 6 string s; 7 bool vis[100005]; 8 int main(){ 9 ios::sync_with_stdio(false); 10 cin>>s; 11 int n = s.length(); 12 for(int l=1;l<n;l++){ 13 if(n%l==0){ 14 for(int i=0;i<l;i++){ 15 //如果在>=l的位置有解那么<l的位置一定也有解 16 int pos = i; 17 while (pos<n&&s[pos]==‘R‘){ 18 pos+=l; 19 } 20 if(pos>=n){ 21 vis[l]=true; 22 } 23 } 24 } 25 } 26 int ans = 0; 27 for(int i=1;i<n;i++){ 28 if(vis[gcd(i,n)]) 29 ans++; 30 } 31 cout<<ans<<endl; 32 }
I:次小生成树板子题,题意不说了很简单。很久没写过LCA的题了今天算是复习了一下。
对于给定的那条边,如果本来就在MST里,直接输出,如果不在,减去两点间的最长路径即可,最长路径和LCA的数组一起处理就可以。
1 #include <bits/stdc++.h> 2 using namespace std; 3 const int N = 1e5+5; 4 5 map<pair<int,int>,int>mt; 6 7 int fa[N],ran[N]; 8 int find(int a){ 9 if(a==fa[a])return a; 10 return fa[a]=find(fa[a]); 11 } 12 void unite(int x,int y){ 13 x = find(x); 14 y = find(y); 15 if(x==y) return; 16 if(ran[x]<ran[y])fa[x]=y; 17 else{ 18 fa[y]=x; 19 if(ran[x]==ran[y]) 20 ran[x]++; 21 } 22 } 23 bool same(int x,int y){ 24 return find(x)==find(y); 25 } 26 27 vector<int>g[N],val[N]; 28 int par[N][22],maxx[N][22],dep[N]; 29 void dfs(int v,int fa){ 30 for(int i=0;i<g[v].size();i++){ 31 int u = g[v][i]; 32 if(u==fa) 33 continue; 34 dep[u]=dep[v]+1; 35 par[u][0]=v; 36 maxx[u][0]=val[v][i]; 37 dfs(u,v); 38 } 39 } 40 41 int lca_(int x,int y) { 42 if (dep[x] > dep[y]) 43 swap(x, y); 44 int tmp1 = mt[make_pair(x, y)];// 45 int res = 0; 46 for (int i = 20; i >= 0; i--){ 47 if (dep[y] - dep[x] >= (1 << i)) { 48 res = max(res,maxx[y][i]); 49 y = par[y][i]; 50 } 51 } 52 if(x==y) 53 return tmp1-res;//多的长度 54 //这两个一定在同一高度了 55 for(int i=20;i>=0;i--) { 56 if (par[x][i] == par[y][i]) 57 continue; 58 else { 59 res = max(res,maxx[x][i]); 60 res = max(res,maxx[y][i]); 61 x = par[x][i], y = par[y][i]; 62 } 63 } 64 res = max(res,maxx[x][0]); 65 res = max(res,maxx[y][0]); 66 return tmp1-res; 67 } 68 69 struct Edge{ 70 int from,to,cost; 71 Edge(){} 72 Edge(int from,int to,int cost):from(from),to(to),cost(cost){} 73 bool operator <(const Edge &b)const { 74 return cost<b.cost; 75 } 76 }edg[200005]; 77 78 int n,m,q,a,b,c; 79 80 void init(){ 81 for(int j=1;(1<<j)<=n;j++){ 82 for(int i=1;i<=n;i++){ 83 par[i][j]=par[par[i][j-1]][j-1]; 84 maxx[i][j]=max(maxx[i][j-1],maxx[par[i][j-1]][j-1]); 85 } 86 } 87 } 88 89 int main(){ 90 ios::sync_with_stdio(false); 91 for(int i=1;i<=100000;i++){ 92 fa[i]=i,ran[i]=0; 93 } 94 cin>>n>>m; 95 for(int i=1;i<=m;i++){ 96 cin>>a>>b>>c; 97 edg[i]=Edge(a,b,c); 98 mt[make_pair(a,b)]=c; 99 mt[make_pair(b,a)]=c; 100 } 101 sort(edg+1,edg+1+m); 102 int ans = 0; 103 for(int i=1;i<=m;i++){ 104 int u = edg[i].from,v = edg[i].to,cost = edg[i].cost; 105 if(!same(u,v)){ 106 unite(u,v); 107 ans+=cost; 108 g[u].push_back(v); 109 g[v].push_back(u); 110 val[u].push_back(cost); 111 val[v].push_back(cost); 112 } 113 } 114 dep[1]=1;dfs(1,1); 115 init(); 116 //cout<<ans<<endl; 117 cin>>q; 118 while (q--){ 119 cin>>a>>b; 120 if(par[a][0]==b||par[b][0]==a)//本来就在MST里 121 cout<<ans<<endl; 122 else{ 123 cout<<ans+lca_(a,b)<<endl; 124 } 125 } 126 }
F:离散化+树状数组。因为我是先学的线段树所以对树状数组不太熟。。。但还是能写下来的(((
思路:两个值都相同的先合并,然后按一维排序,另一维做最大上升子序列权值和。
1 #include <bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 const int N = 100005; 5 struct node{ 6 int a,b; 7 ll cost; 8 }p[N]; 9 int n,s[N*4];//离散化 10 map<pair<int,int>, ll> m; 11 vector<int> l[N*4]; 12 ll c[N*4]; 13 int lowbit(int k){ return k&-k;} 14 void update(int pos,ll num){ 15 while (pos<=4*N){ 16 c[pos]=max(c[pos],num); 17 pos+=lowbit(pos); 18 } 19 } 20 ll maxx(int pos){ 21 ll s = 0; 22 while (pos>0){ 23 s=max(s,c[pos]); 24 pos-=lowbit(pos); 25 } 26 return s; 27 } 28 int cmp(int a,int b){ 29 return a>b; 30 } 31 int main(){ 32 ios::sync_with_stdio(false); 33 cin>>n; 34 for(int i=1;i<=n;i++){ 35 cin>>p[i].a>>p[i].b>>p[i].cost; 36 s[2*i]=p[i].a; 37 s[2*i-1]=p[i].b; 38 } 39 sort(s+1,s+2*n+1); 40 int cnt = unique(s+1,s+2*n+1)-s-1; 41 for(int i=1;i<=n;i++){ 42 int a = lower_bound(s+1,s+1+cnt,p[i].a)-s; 43 int b = lower_bound(s+1,s+1+cnt,p[i].b)-s; 44 m[make_pair(a,b)]+=p[i].cost; 45 l[a].push_back(b); 46 } 47 for(int i=1;i<=cnt;i++){ 48 sort(l[i].begin(),l[i].end(),cmp); 49 for(int j=0;j<l[i].size();j++){ 50 int b = l[i][j]; 51 ll tmp = maxx(b-1); 52 ll all = tmp+m[make_pair(i,b)]; 53 update(b,all); 54 } 55 } 56 cout<<maxx(cnt)<<endl; 57 }
以上是关于2017-2018 ACM-ICPC Latin American Regional Programming Contest GYM101889的主要内容,如果未能解决你的问题,请参考以下文章
2017-2018 ACM-ICPC Latin American Regional Programming Contest GYM101889
2017-2018 ACM-ICPC Latin American Regional Programming Contest Solution
2019-2020 ACM-ICPC Latin American Regional Programming Contest L - Leverage MDT
2019-2020 ACM-ICPC Latin American Regional Programming Contest A- Algorithm Teaching 二分图
2019-2020 ACM-ICPC Latin American Regional Programming Contest I - Improve SPAM 树形dp?