2017-2018 ACM-ICPC Latin American Regional Programming Contest GYM101889
阿新 • • 發佈:2018-10-17
val bool b- truct 之前 排序 數位dp pen swap
挺有意思的一套題,題也沒有啥毒瘤了,本來是隊切的結果種種原因大家全掛機了。
只補了百人題,一共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++)View Code8 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;View Codeint 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 }View Code
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 }View Code
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 }View Code
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 }View Code
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 }View Code
2017-2018 ACM-ICPC Latin American Regional Programming Contest GYM101889