4-25ACM训练题解(gym 102392)

D  Cycle string Gym - 102392D by ltr

我们可以发现,当所有字母出现次数都<=n时,我们只要把所有字母排序就一定可以满足条件,因为不可能有两个首字母相同的子串他们首字母出现的次数也相同。

当有一个字母出现次数>n时,我们分类讨论,若出现次数为2*n或2*n-1,显然无解,当出现次数为2*n-2时,若另外两个字母不同,则有解,我们可以排成A……ABA……AC的形式,若相同,则无解。

当出现次数<=2*n-3时,我们排成A……ABA……CCDD……E的形式即为答案。

  1 #include<iostream>
  2 #include<cstdlib>
  3 #include<cstdio>
  4 #include<cstring>
  5 #include<algorithm>
  6 #include<cmath>
  7 #include<queue>
  8 #include<map>
  9 #define N 1000005
 10 using namespace std;
 11 char B[N];
 12 int cnt[30];
 13 int ans[N],n;
 14 int js;
 15 int main()
 16 {
 17     scanf("%s",B+1);
 18     n=strlen(B+1);
 19     for(int i=1;i<=n;i++)
 20     {
 21         cnt[B[i]-'a'+1]++;
 22         if(cnt[B[i]-'a'+1]==1) js++;
 23     }
 24     int mx=0,bj=-1;;
 25     for(int i=1;i<=26;i++)
 26     {
 27         mx=max(mx,cnt[i]);
 28         if(mx==cnt[i]) bj=i;
 29     }
 30     if(mx<=n/2)
 31     {
 32         printf("YES\n");
 33         int zz=0;
 34         for(int i=1;i<=26;i++)
 35         {
 36             while(cnt[i])
 37             {
 38                 zz++;
 39                 ans[zz]=i;
 40                 cnt[i]--;
 41             }
 42         }
 43         for(int i=1;i<=n;i++)
 44         {
 45             printf("%c",(char)ans[i]+'a'-1);
 46         }
 47     }
 48     else
 49     {
 50         if(mx==n||mx==n-1)
 51         {
 52             printf("NO\n");
 53         }
 54         else if(mx==n-2)
 55         {
 56             if(js==2)
 57             {
 58                 printf("NO\n");
 59             }
 60             else
 61             {
 62                 for(int i=1;i<=26;i++)
 63                 {
 64                     if(cnt[i]!=mx&&cnt[i])
 65                     {
 66                         ans[n/2]=i;
 67                         cnt[i]--;
 68                         break;
 69                     }
 70                 }
 71                 for(int i=1;i<=26;i++)
 72                 {
 73                     if(cnt[i]!=mx&&cnt[i])
 74                     {
 75                         ans[n]=i;
 76                         cnt[i]--;
 77                         break;
 78                     }
 79                 }
 80                 for(int i=1;i<=n;i++)
 81                 {
 82                     if(i!=n&&i!=n/2) ans[i]=bj;
 83                 }
 84                 printf("YES\n");
 85                 for(int i=1;i<=n;i++)
 86                 {
 87                     printf("%c",(char)ans[i]+'a'-1);
 88                 }
 89             }
 90         }
 91         else
 92         {
 93             printf("YES\n");
 94             for(int i=1;i<=26;i++)
 95             {
 96                 if(cnt[i]!=mx&&cnt[i])
 97                 {
 98                     ans[n/2]=i;
 99                     cnt[i]--;
100                     break;
101                 }
102             }
103             for(int i=1;i<n/2;i++)
104             {
105                 ans[i]=bj;
106             }
107             for(int i=n/2+1;i<=mx+1;i++)
108             {
109                 ans[i]=bj;
110             }
111         
112             cnt[bj]=0;
113             int now=0;
114             for(int i=mx+2;i<=n;i++)
115             {
116                 while(!cnt[now]) now++;
117                 ans[i]=now;
118                 cnt[now]--;
119             }
120             
121             for(int i=1;i<=n;i++)
122             {
123                 printf("%c",(char)ans[i]+'a'-1);
124             }
125         }
126     }
127     return 0;
128 }
View Code

E Life transfer Gym - 102392E  by ltr

我们可以先贪心得到一个结论,如果我们将人的年龄从小到大排列,那么一定是较小的坐车,较大的开车,中间一部分人骑车,这样一定不劣,原因显然。那么,我们可以去枚举有多少人坐车,当我们知道有多少人坐车,则开车和骑车的人数也都知道了,这里主要靠一些桶来维护,细节很多。

首先,我们要保证做摩托车的人他们在被分配d的年龄时都到达了年龄限制。

其次,我们我们要保证开车的人在被分配d的年龄的时候达到了年龄限制。

还有就是从小到大枚举的坐车的人和从大到小枚举的开车的人不会交叉重复。

 1 #include<iostream>
 2 #include<cstdlib>
 3 #include<cstdio>
 4 #include<cstring>
 5 #include<algorithm>
 6 #include<cmath>
 7 #include<queue>
 8 #include<map>
 9 #define N 100005
10 using namespace std;
11 int n,K;
12 long long lc,pc,lm,pm,t,d;
13 int A[N];
14 long long ans=1e18;
15 long long sm[N],to[N],sum;
16 int l1,l2;
17 int main()
18 {
19     scanf("%d%d",&n,&K);
20     scanf("%lld%lld%lld%lld",&lc,&pc,&lm,&pm);
21     scanf("%lld%lld",&t,&d);
22     for(int i=1;i<=n;i++)scanf("%d",&A[i]);
23     sort(A+1,A+n+1);
24     
25     for(int i=1;i<=n;i++)
26     {
27         if(A[i]<lm)
28         {
29             l1=i;
30         }
31         else break;
32     }
33     for(int i=l1;i;i--)
34     {
35         sm[i]=sm[i+1]+lm-A[i];
36         to[i]=A[i];
37     }
38     for(int i=l1+1;i<=n;i++)
39     {
40         if(A[i]-d>=lm) to[i]=A[i]-d,sum+=d;
41         else to[i]=lm,sum+=A[i]-lm;    
42     }
43     int zz1=n+1;
44 
45     if(sm[1]<=sum&&A[1]+d>=lm)
46     {
47         ans=1ll*sm[1]*t+1ll*n*pm;
48     }
49     if(K!=1)
50     {
51         long long tmp=0;
52         for(int i=1;i<=n;i++)
53         {
54             if(A[i]>d) sum+=d;
55             else sum+=A[i]-1;
56             if((i+(K-2))/(K-1)>n-zz1+1)
57             {
58                 zz1--;
59                 if(A[zz1]<lc)
60                 {
61                     tmp+=lc-A[zz1];
62                     sum-=A[zz1]-to[zz1];
63                 }
64                 else if(to[zz1]<lc)
65                 {
66                     sum-=lc-to[zz1];
67                 }
68                 if(A[zz1]+d<lc)
69                 {
70                     break;
71                 }
72             }
73                     
74             if(A[i+1]+d<lm&&zz1>i+1) continue;
75             if(sm[i+1]-sm[zz1]+tmp<=sum&&zz1>i)
76             {
77                 ans=min(ans,1ll*t*(sm[i+1]-sm[zz1]+tmp)+1ll*(n-zz1+1)*pc+1ll*(zz1-i-1)*pm);
78             }
79         }
80     }
81     if(ans==1e18) printf("-1\n");
82     else printf("%lld\n",ans);
83     return 0;
84 }
View Code

F Game on a tree Gym - 102392F by myl

博弈论问题

思考Bob获胜的条件,即Alice每走一步,Bob都有合法的一步可走

通过树形dp,对树进行匹配,如果得到完美匹配则Bob胜利,否则Alice胜利

 1 #include<cstdio>
 2 
 3 int a,b,c,d,e,f,g,m,n;
 4 int xa[500000]={0},xb[500000]={0};
 5 int wa[500000]={0},wb[500000]={0};
 6 
 7 int df(int j)
 8 {
 9 int k,r,s;
10 k=0;
11 xa[j]=1;
12 r=xb[j];
13 s=wa[r];
14 while(r!=0)
15 {
16     if(xa[s]==0) k+=df(s);
17     r=wb[r];
18     s=wa[r];
19 }
20 k--;
21 if(k<0) k=1;
22 return k;
23 }
24 
25 int main()
26 {
27 int i,j,k;
28 scanf("%d",&n);
29 for(i=1;i<n;i++)
30 {
31     scanf("%d%d",&a,&b);
32     wa[2*i-1]=b;
33     wb[2*i-1]=xb[a];
34     xb[a]=2*i-1;
35     wa[2*i]=a;
36     wb[2*i]=xb[b];
37     xb[b]=2*i;
38 }
39 if((n%2==0)&&(df(1)==0)) printf("Bob\n");
40 else printf("Alice\n");
41 }
View Code

G projection Gym - 102392G  by ltr

贪心,为了方便,我们可以把他一层一层的进行处理。

求最大的时候很简单,所有交叉点都放上方块

求最小的时候稍有麻烦,我们设长(y)上共有cnt[0]个阴影,宽(z)上有cnt[1]个阴影,则为了满足字典序最小,我们要分类讨论。

cnt[0]>=cnt[1],则长上前cnt[0]-cnt[1]+1个阴影都与宽上第一个阴影对应,剩下的点依次与宽上第2个,第3个……对应。

cnt[1]>cnt[0],则宽上前cnt[1]-cnt[0]+1个阴影都与长上第一个阴影对应,剩下的点依次与长上第2个,第3个……对应。

  1 #include<iostream>
  2 #include<cstdlib>
  3 #include<cstdio>
  4 #include<cstring>
  5 #include<algorithm>
  6 #include<cmath>
  7 #include<queue>
  8 #include<map>
  9 #define N 105
 10 using namespace std;
 11 int n,m,h;
 12 struct no{
 13     int x,y,z;
 14 }node[N*N*N];
 15 bool cmp(const no &a,const no &b)
 16 {
 17     if(a.x==b.x&&a.y==b.y)return a.z<b.z;
 18     if(a.x==b.x)return a.y<b.y;
 19     return a.x<b.x;
 20 }
 21 char B[N];
 22 int ma1[N][N],ma2[N][N];
 23 int q[2][N];
 24 int zz=0;
 25 int main()
 26 {
 27 //    freopen("test.in","r",stdin);
 28 //    freopen("1.out","w",stdout);
 29     scanf("%d%d%d",&n,&m,&h);
 30     for(int i=1;i<=n;i++)
 31     {
 32         scanf("%s",B+1);
 33         for(int j=1;j<=m;j++)
 34         {
 35             ma1[i][j]=(B[j]=='1');
 36         } 
 37     }
 38     for(int i=1;i<=n;i++)
 39     {
 40         scanf("%s",B+1);
 41         for(int j=1;j<=h;j++)
 42         {
 43             ma2[i][j]=(B[j]=='1');
 44         } 
 45     }
 46     bool yx=1;
 47     for(int i=1;i<=n;i++)
 48     {
 49         q[1][0]=q[0][0]=0;
 50         for(int j=1;j<=m;j++)
 51         {
 52             if(ma1[i][j])
 53             {
 54                 q[0][0]++;
 55                 q[0][q[0][0]]=j;
 56             }
 57         }
 58         for(int j=1;j<=h;j++)
 59         {
 60             if(ma2[i][j])
 61             {
 62                 q[1][0]++;
 63                 q[1][q[1][0]]=j;
 64             }
 65         }
 66         if(!q[1][0]&&q[0][0]) yx=0;
 67         if(q[1][0]&&!q[0][0]) yx=0;
 68         for(int j=1;j<=q[0][0];j++)
 69         {
 70             for(int k=1;k<=q[1][0];k++)
 71             {
 72                 zz++;
 73                 node[zz].x=i,node[zz].y=q[0][j],node[zz].z=q[1][k];
 74             }
 75         }
 76     }
 77     if(!yx)
 78     {
 79         printf("-1\n");
 80         return 0;
 81     }
 82     sort(node+1,node+zz+1,cmp);
 83     printf("%d\n",zz);
 84     for(int i=1;i<=zz;i++)
 85     {
 86         printf("%d %d %d\n",node[i].x-1,node[i].y-1,node[i].z-1);
 87     }
 88     zz=0;
 89     for(int i=1;i<=n;i++)
 90     {
 91         q[1][0]=q[0][0]=0;
 92         for(int j=1;j<=m;j++)
 93         {
 94             if(ma1[i][j])
 95             {
 96                 q[0][0]++;
 97                 q[0][q[0][0]]=j;
 98             }
 99         }
100         for(int j=1;j<=h;j++)
101         {
102             if(ma2[i][j])
103             {
104                 q[1][0]++;
105                 q[1][q[1][0]]=j;
106             }
107         }
108         if(q[0][0]<=q[1][0])
109         {
110             for(int j=1;j<=q[1][0]-q[0][0];j++)
111             {
112                 zz++;
113                 node[zz].x=i;
114                 node[zz].y=q[0][1];
115                 node[zz].z=q[1][j];
116             }
117             for(int j=1;j<=q[0][0];j++)
118             {
119                 zz++;
120                 node[zz].x=i;
121                 node[zz].y=q[0][j];
122                 node[zz].z=q[1][j+q[1][0]-q[0][0]];
123             }
124         }
125         else
126         {
127             for(int j=1;j<=q[0][0]-q[1][0];j++)
128             {
129                 zz++;
130                 node[zz].x=i;
131                 node[zz].y=q[0][j];
132                 node[zz].z=q[1][1];
133             }
134             for(int j=1;j<=q[1][0];j++)
135             {
136                 zz++;
137                 node[zz].x=i;
138                 node[zz].y=q[0][q[0][0]-q[1][0]+j];
139                 node[zz].z=q[1][j];
140             }
141         }
142     }
143     printf("%d\n",zz);
144     sort(node+1,node+zz+1,cmp);
145     for(int i=1;i<=zz;i++)
146     {
147         printf("%d %d %d\n",node[i].x-1,node[i].y-1,node[i].z-1);
148     }
149     return 0;
150 }
View Code

I Absolute Game Gym - 102392I  by myl

博弈论

由于n只有1000,直接暴力枚举所有情况,找到所以最大的最小值,即为最终的答案

 1 #include<cstdio>
 2 
 3 int a,b,c,d,e,f,g,m,n;
 4 int xa[200000]={0},xb[200000]={0};
 5 
 6 void ma(int &j,int k)
 7 {
 8 if(j<k) j=k;
 9 }
10 
11 void mi(int &j,int k)
12 {
13 if(j>k) j=k;
14 }
15 
16 int zh(int j)
17 {
18 if(j<0) return -j;
19 return j;
20 }
21 
22 int main()
23 {
24 int i,j,k;
25 scanf("%d",&n);
26 for(i=1;i<=n;i++)
27 {
28     scanf("%d",&xa[i]);
29 }
30 for(i=1;i<=n;i++)
31 {
32     scanf("%d",&xb[i]);
33 }
34 a=0;
35 for(i=1;i<=n;i++)
36 {
37     b=zh(xa[i]-xb[n]);
38     for(j=1;j<n;j++)
39     {
40         mi(b,zh(xa[i]-xb[j]));
41     }
42     ma(a,b);
43 }
44 printf("%d\n",a);
45 }
View Code

J Graph and Cycles Gym - 102392J  by wxh

对于这道题,单独考虑每个点,在任何一个环中必然是选择两个值连续的边。
那么我们对每个点的边排序,加上每两个边的大值就可以了

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 struct data {
 4   int END, v, next;
 5 }v[997007];
 6 int first[1000], p;
 7 void add(int a, int b, int c) {
 8   v[p].END = b;
 9   v[p].v = c;
10   v[p].next = first[a];
11   first[a] = p++;
12 }
13 vector<int> vc;
14 int main() {
15   int n, m;
16   memset (first, -1, sizeof(first));
17   scanf ("%d", &n);
18   m = n * (n - 1) / 2;
19   int a, b, c;
20   for (int i = 1; i <= m; i++) {
21     scanf ("%d%d%d", &a, &b, &c);
22     add(a, b, c);
23     add(b, a, c);
24   }
25   long long ans = 0;
26   for (int i = 1; i <= n; i++) {
27     vc.clear();
28     for (int j = first[i]; j != -1; j = v[j].next) {
29       vc.push_back(v[j].v);
30     }
31     sort(vc.begin(), vc.end(), greater<int>());
32     for (int j = 0; j < vc.size(); j += 2) {
33       ans += vc[j];
34     }
35   }
36   printf ("%lld\n", ans);
37 }
View Code
posted @ 2020-04-27 21:34  Hzoi_joker  阅读(452)  评论(0编辑  收藏  举报