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 }
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

 

posted @ 2018-10-17 00:36  MXang  阅读(529)  评论(0编辑  收藏  举报