1. 程式人生 > >2017-2018 ACM-ICPC Latin American Regional Programming Contest GYM101889

2017-2018 ACM-ICPC Latin American Regional Programming Contest GYM101889

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++)
8 ans+=max(0,b[i]-a[i]); 9 cout<<ans<<endl; 10 }
View Code

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; } } }
View Code

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