5-2ACM训练题解(Asia Nakhon Pathom Regional Contest)

C-Evolution Game Gym - 102091C  by wxh

按单增的维度排序,然后另一个维度DP,就和最初的n^2求最长递增子序列相似。
N^2跑就行

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 struct data {
 4   int a, b;
 5 }a[5005];
 6 int F[5005];
 7 int T[5005];
 8 int main() {
 9   int N, w;
10   scanf ("%d%d", &N, &w);
11   for (int i = 1; i <= N; i++) {
12     scanf ("%d", &a[i].a);
13     T[i] = a[i].a;
14     a[i].b = i;
15   }
16   sort (a + 1, a + N + 1, [&] (data &x, data &y) -> bool{
17     return x.a == y.a ? x.b < y.b : x.a < y.a;
18   });
19   int ans = 0;
20   for (int i = 1; i <= N; i++) {
21     F[i] = 0;
22     for (int j = 1; j <= i; j++) {
23       if (a[j].a < a[i].a && abs(a[j].b - a[i].b) <= w) {
24         F[i] = max(F[i], F[j] + 1);
25         ans = max(ans, F[i]);
26       }
27     }
28   }
29   printf ("%d\n", ans);
30 }
View Code

D-Bus Stop Gym - 102091D  by ltr

贪心签到,从左往右贪心看能否放车站即可

 1 #include<iostream>
 2 #include<cstdlib>
 3 #include<cstdio>
 4 #include<algorithm>
 5 #include<cstring>
 6 #include<cmath>
 7 #define N 2000005
 8 using namespace std;
 9 int n,T;
10 int A[N];
11 int main()
12 {
13     scanf("%d",&T);
14     while(T--)
15     {
16         scanf("%d",&n);
17         for(int i=1;i<=n;i++)
18         {
19             scanf("%d",&A[i]);
20         }
21         int la=1,cnt=0;
22         for(int i=2;i<=n;i++)
23         {
24             if(A[i]-A[la]>20)
25             {
26                 cnt++,la=i;
27             }
28             if(i==n)
29             {
30                 cnt++;
31             }
32         }
33         printf("%d\n",cnt);
34         
35     }
36     return 0;
37 }
View Code

E-How Many Groups Gym - 102091E  by ltr

dp,我们先将数组排序,然后设定dp数组f[i][j][k],表示从1~i中用了j次操作,且i-1的状态为k(0表示不变,1表示-1,2表示+1),然后转移即可,在代码里我用的滚动数组替代第一维。

 1 #include<iostream>
 2 #include<cstdlib>
 3 #include<cstdio>
 4 #include<algorithm>
 5 #include<cstring>
 6 #include<cmath>
 7 #define N 105
 8 using namespace std;
 9 int T,n,A[N],f[2][3][3];
10 int main()
11 {
12     scanf("%d",&T);
13     int cnt=0;
14     while(T--)
15     {
16         scanf("%d",&n);
17         for(int i=1;i<=n;i++)
18         {
19             scanf("%d",&A[i]);
20         }
21         sort(A+1,A+n+1);
22         int ans=1;
23         int nw=1,la=0;
24         memset(f,0,sizeof(f));
25         f[nw][0][0]=1;
26         f[nw][1][1]=1;
27         f[nw][1][2]=1;
28         for(int i=2;i<=n;i++)
29         {
30             nw^=1,la^=1;
31             memset(f[nw],0,sizeof(f[nw]));
32             if(A[i]-A[i-1]<=2)
33             {
34                 f[nw][0][0]=max(f[nw][0][0],f[la][0][0]+1);
35                 f[nw][1][0]=max(f[nw][1][0],f[la][1][0]+1);
36                 f[nw][2][0]=max(f[nw][2][0],f[la][2][0]+1);
37             }
38             if(abs(A[i]-(A[i-1]-1))<=2)
39             {
40                 f[nw][1][0]=max(f[nw][1][0],f[la][1][1]+1);
41                 f[nw][2][0]=max(f[nw][2][0],f[la][2][1]+1);
42             }
43             if(abs(A[i]-(A[i-1]+1))<=2)
44             {
45                 f[nw][1][0]=max(f[nw][1][0],f[la][1][2]+1);
46                 f[nw][2][0]=max(f[nw][2][0],f[la][2][2]+1);
47             }
48             if(abs(A[i]-1-A[i-1])<=2)
49             {
50                 f[nw][1][1]=max(f[nw][1][1],f[la][0][0]+1);
51                 f[nw][2][1]=max(f[nw][2][1],f[la][1][0]+1);
52             }
53             if(abs(A[i]+1-A[i-1])<=2)
54             {
55                 f[nw][1][2]=max(f[nw][1][2],f[la][0][0]+1);
56                 f[nw][2][2]=max(f[nw][2][2],f[la][1][0]+1);
57             }
58             
59             if(abs((A[i]-1)-(A[i-1]-1))<=2)
60             {
61                 f[nw][2][1]=max(f[nw][2][1],f[la][1][1]+1);
62             }
63             if(abs((A[i]+1)-(A[i-1]+1))<=2)
64             {
65                 f[nw][2][2]=max(f[nw][2][2],f[la][1][2]+1);
66             }
67             
68             if(abs((A[i]-1)-(A[i-1]+1))<=2)
69             {
70                 f[nw][2][1]=max(f[nw][2][1],f[la][1][2]+1);
71             }
72             if(abs((A[i]+1)-(A[i-1]-1))<=2)
73             {
74                 f[nw][2][2]=max(f[nw][2][2],f[la][1][1]+1);
75             }
76             if(!f[nw][0][0]) f[nw][0][0]=1;
77             for(int j=1;j<=2;j++)
78             {
79                 for(int k=0;k<=2;k++)
80                 {
81                     if(!f[nw][j][k]) f[nw][j][k]=1;
82                     ans=max(ans,f[nw][j][k]);
83                 }
84             }
85             
86             ans=max(ans,f[nw][0][0]);
87         }
88         cnt++;
89         printf("Case %d: %d\n",cnt,ans);
90     }
91     return 0;
92 }
View Code

F-Lucky Pascal Triangle Gym - 102091F  by wxh

打表找规律,然后递归求解就可以了

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 const int MOD = 1e9 + 7, Inv2 = 500000004;
 4 long long bin[25], D[25];
 5 int Calc(long long a, int L) {
 6   if (a <= 7) return 0;
 7   int T = a / bin[L];
 8   // long long d = (bin[L] * 2 - a % bin[L] - 1) % MOD;
 9   long long ans = (bin[L] * 2 - a % bin[L] - 1) % MOD * ((a % bin[L]) % MOD) % MOD * Inv2 % MOD * (a / bin[L]) % MOD;
10   ans = (ans + 1ll * Calc(a % bin[L], L - 1) * (a / bin[L] + 1) % MOD) % MOD;
11   ans = (ans + 1ll * D[L] * (1 + T) * T % MOD * Inv2 % MOD + bin[L] % MOD * ((bin[L] - 1) % MOD) % MOD * Inv2 % MOD * T * (T - 1) % MOD * Inv2 % MOD) % MOD;
12   return ans;
13 }
14 int main() {
15   int N;
16   scanf ("%d", &N);
17   long long a = 0;
18   bin[0] = 1;
19   for (int i = 1; i <= 22; i++) bin[i] = bin[i - 1] * 7;
20 //   for (int i = 1; i <= 22; i++) printf ("%lld\n", bin[i]);
21   for (int i = 1; i <= 22; i++) D[i] = Calc(bin[i] - 1, i - 1);
22   for (int i = 1; i <= N; i++) {
23     scanf ("%lld", &a);
24     int L;
25     for (L = 22; L >= 1; L--) {
26       if (a >= bin[L])
27         break;
28     }
29     printf ("Case %d: %d\n", i, Calc(a + 1, L));
30   }
31 }
View Code

G-Communication Gym - 102091G  by ltr

题意说的很奇怪,算是“心灵相通”A掉的,在这里大概说一下题意,就是一开始有n个办公室,之间有单向边,如果他们之间都能直接或间接到达,则他们是一个部门,问你总共有多少部门。

说白了就是一个数联通块的题……tarjan板子放上去就可以了

 1 #include<iostream>
 2 #include<cstdlib>
 3 #include<cstdio>
 4 #include<algorithm>
 5 #include<cstring>
 6 #include<cmath>
 7 #define N 205
 8 using namespace std;
 9 int T,n,m,zz,a[N];
10 struct ro{
11     int to,next;
12 }road[N*N];
13 void build(int x,int y)
14 {
15     zz++;
16     road[zz].to=y;
17     road[zz].next=a[x];
18     a[x]=zz;
19 }
20 int dfn[N],low[N],zz1,st[N],top,zz2;
21 bool rd[N];
22 void tarjan(int x)
23 {
24     zz1++;
25     dfn[x]=low[x]=zz1;
26     top++;
27     st[top]=x;
28     rd[x]=1;
29     for(int i=a[x];i;i=road[i].next)
30     {
31         int y=road[i].to;
32         if(!dfn[y])
33         {
34             tarjan(y);
35             low[x]=min(low[x],low[y]);
36         }
37         else if(rd[y])
38         {
39             low[x]=min(low[x],dfn[y]);
40         }
41     }
42     if(low[x]==dfn[x])
43     {
44         zz2++;
45         int v;
46         do{
47             v=st[top];
48             top--;
49             rd[v]=0;
50         }while(dfn[v]!=low[v]);
51     }
52 }
53 int main()
54 {
55     scanf("%d",&T);
56     while(T--)
57     {
58         scanf("%d%d",&n,&m);
59         zz=0;
60         memset(a,0,sizeof(a));
61         for(int i=1;i<=m;i++)
62         {
63             int x,y;
64             scanf("%d%d",&x,&y);
65             x++,y++;
66             build(x,y);
67         }
68         zz1=zz2=0;
69         memset(dfn,0,sizeof(dfn));
70         memset(low,0,sizeof(low));
71         for(int i=1;i<=n;i++)
72         {
73             if(!dfn[i])
74             {
75                 tarjan(i);
76             }
77         }    
78         printf("%d\n",zz2);
79     }
80     return 0;
81 }
View Code

J-Floating-point Hazard Gym - 102091J  by wxh

$$\sum_{i=low}^{high} {(\sqrt[3]{(i+10^{-15})}-\sqrt[3]{i})} \approx \sum_{i=low}^{high} {\lim_{x->0} (\sqrt[3]{(i+x)}-\sqrt[3]{i})} = \sum_{i=low}^{high}{f'(i) \times 10^{-15}}$$
然后按导数求就可以了

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 int main() {
 4   long long a, b;
 5   while (scanf ("%lld%lld", &a, &b) != EOF) {
 6     if (a == 0 && b == 0) break;
 7     double ans = 0;
 8     for (int i = a; i <= b; i++) {
 9       ans += 1. / 3 * pow(i, -2. / 3);
10     }
11     printf ("%.5E\n", ans * 1e-15);
12   }
13 }
View Code

K-The Sream of Corning 2 Gym - 102091K  by ltr

这道题好像解法挺多,我是直接将输入的值离散化,将操作1拆成加入和删除两个操作,然后在线段树上找前缀和>=K的第一个值,不难,但是训练的时候没看到……

  1 #include<iostream>
  2 #include<cstdlib>
  3 #include<cstdio>
  4 #include<cstring>
  5 #include<cmath>
  6 #include<map>
  7 #include<algorithm>
  8 #define N 100005
  9 using namespace std;
 10 int T,m,zz;
 11 struct qu{
 12     int id,op,x,y,z;
 13 }que[N*2];
 14 bool cmp(const qu &a,const qu &b)
 15 {
 16     if(a.x!=b.x)return a.x<b.x;
 17     return a.op<b.op;
 18 }
 19 int zz2,B[N];
 20 struct no{
 21     int left,right,mid,size;
 22 }node[N*4];
 23 void build(int left,int right,int x)
 24 {
 25     node[x].left=left,node[x].right=right;
 26     node[x].size=0;
 27     if(left==right)
 28     {
 29         return;
 30     } 
 31     int mid=(left+right)>>1;
 32     node[x].mid=mid;
 33     build(left,mid,x<<1);
 34     build(mid+1,right,x<<1|1);
 35 }
 36 map<int,int> ma;
 37 void add(int x,int to,int da)
 38 {
 39     if(node[x].left==node[x].right)
 40     {
 41         node[x].size+=da;
 42         return;
 43     }
 44     int mid=node[x].mid;
 45     if(to>mid) add(x<<1|1,to,da);
 46     else add(x<<1,to,da);
 47     node[x].size=node[x<<1].size+node[x<<1|1].size;
 48 }
 49 int work(int x,int da)
 50 {
 51     if(node[x].left==node[x].right)return node[x].left;
 52     int mid=node[x].mid;
 53     if(node[x<<1].size>=da)
 54     {
 55         return work(x<<1,da);
 56     }
 57     else return work(x<<1|1,da-node[x<<1].size);
 58 }
 59 int ans[N];
 60 int main()
 61 {
 62     scanf("%d",&T);
 63     int cnt=0;
 64     while(T--)
 65     {
 66         cnt++;
 67         scanf("%d",&m);
 68         zz=0;
 69         zz2=0;
 70         int zz3=0;
 71         ma.clear();
 72         for(int i=1;i<=m;i++)
 73         {
 74             zz++;
 75             scanf("%d",&que[zz].op);
 76             que[zz].id=i;
 77             if(que[zz].op==1)
 78             {
 79                 scanf("%d%d%d",&que[zz].x,&que[zz].y,&que[zz].z);
 80                 zz++;
 81                 que[zz].id=i,que[zz].op=3,que[zz].x=que[zz-1].z;
 82                 que[zz].y=que[zz-1].y;
 83                 if(!ma.count(que[zz].y))
 84                 {
 85                     ma[que[zz].y]=1;
 86                     zz2++;
 87                     B[zz2]=que[zz].y;
 88                 }
 89             }
 90             else
 91             {
 92                 zz3++;
 93                 que[zz].id=zz3;
 94                 scanf("%d%d",&que[zz].x,&que[zz].y);
 95             }
 96         }
 97         sort(que+1,que+zz+1,cmp);
 98         sort(B+1,B+zz2+1);
 99         for(int i=1;i<=zz2;i++) ma[B[i]]=i;
100         build(1,zz2,1);
101         for(int i=1;i<=zz;i++)
102         {
103             if(que[i].op==1)
104             {
105                 add(1,ma[que[i].y],1);
106             }
107             else if(que[i].op==3) 
108             {
109                 add(1,ma[que[i].y],-1);
110             }
111             else
112             {
113                 if(node[1].size>=que[i].y) ans[que[i].id]=B[work(1,que[i].y)];
114                 else ans[que[i].id]=-1;
115             }
116         }
117         printf("Case %d:\n",cnt);
118         for(int i=1;i<=zz3;i++)
119         {
120             printf("%d\n",ans[i]);
121         }
122     }
123     return 0;
124 }
View Code

L-Largest Allowed Area Gym - 102091L  by ltr

一开始是枚举所选矩形左上角,然后利用二维前缀和进行二分,然后发现T了……

之后发现了一个性质,就是(x,y)的最优解最多为(x,y+1)的最优解+1,然后又加上快读就过了。

A了之后试着把第一次的代码加上快读和二分左端点优化再交,也过了。

之后看了一下网上的题解,说是单调队列,我理解的就是每一行从右往左遍历,用单调队列维护最优右端点。复杂度很优秀。

 1 #include<iostream>
 2 #include<cstdlib>
 3 #include<cstdio>
 4 #include<algorithm>
 5 #include<cstring>
 6 #include<cmath>
 7 #define N 1005
 8 using namespace std;
 9 int n,T,m,ma[N][N],sm[N][N];
10 int get(int x,int y,int ll,int rr)
11 {
12     int l=ll,r=min(rr,min(n-x+1,m-y+1)),mid,ans=1;
13     while(l<=r)
14     {
15         mid=(l+r)>>1;
16         
17         if(sm[x+mid-1][y+mid-1]-sm[x+mid-1][y-1]-sm[x-1][y+mid-1]+sm[x-1][y-1]<=1) ans=mid,l=mid+1;
18         else r=mid-1;
19     }
20     return ans;
21 }
22 char xch,xB[1<<15],*xS=xB,*xTT=xB;
23 #define getc() (xS==xTT&&(xTT=(xS=xB)+fread(xB,1,1<<15,stdin),xS==xTT)?0:*xS++)
24 inline int read()
25 {
26     int x=0,f=1;char ch=getc();
27     while (ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getc();}
28     while (ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getc();}
29     return x*f;
30 }
31 int main()
32 {
33     T=read();
34     while(T--)
35     {
36         n=read(),m=read();
37         for(register int i=1,j;i<=n;++i)
38         {
39             int su=0;
40             for(j=1;j<=m;++j)
41             {
42                 ma[i][j]=read();
43                 su+=ma[i][j];
44                 sm[i][j]=sm[i-1][j]+su;
45             }
46         }
47         int ans=1;
48         for(register int i=1,j;i<=n;++i)
49         {
50             int la=1;
51             for(j=m-1;j;--j)
52             {                 
53                 la=get(i,j,1,la+1);
54                 ans=max(ans,la);
55             }
56         }
57         printf("%d\n",ans);
58     }
59     return 0;
60 }
View Code
 1 #include<iostream>
 2 #include<cstdlib>
 3 #include<cstdio>
 4 #include<algorithm>
 5 #include<cstring>
 6 #include<cmath>
 7 #define N 1005
 8 using namespace std;
 9 int n,T,m,ma[N][N],sm[N][N];
10 int get(int x,int y,int ll)
11 {
12     int l=ll,r=min(n-x+1,m-y+1),mid,ans=1;
13     while(l<=r)
14     {
15         mid=(l+r)>>1;
16         
17         if(sm[x+mid-1][y+mid-1]-sm[x+mid-1][y-1]-sm[x-1][y+mid-1]+sm[x-1][y-1]<=1) ans=mid,l=mid+1;
18         else r=mid-1;
19     }
20     return ans;
21 }
22 char xch,xB[1<<15],*xS=xB,*xTT=xB;
23 #define getc() (xS==xTT&&(xTT=(xS=xB)+fread(xB,1,1<<15,stdin),xS==xTT)?0:*xS++)
24 inline int read()
25 {
26     int x=0,f=1;char ch=getc();
27     while (ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getc();}
28     while (ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getc();}
29     return x*f;
30 }
31 int main()
32 {
33     T=read();
34     while(T--)
35     {
36         n=read(),m=read();
37         for(register int i=1,j;i<=n;++i)
38         {
39             int su=0;
40             for(j=1;j<=m;++j)
41             {
42                 ma[i][j]=read();
43                 su+=ma[i][j];
44                 sm[i][j]=sm[i-1][j]+su;
45             }
46         }
47         int ans=1;
48         for(register int i=1,j;i<=n;++i)
49         {
50             int la=1;
51             for(j=m-1;j;--j)
52             {                 
53                 la=get(i,j,ans);
54                 ans=max(ans,la);
55             }
56         }
57         printf("%d\n",ans);
58     }
59     return 0;
60 }
View Code

 

posted @ 2020-05-05 10:06  Hzoi_joker  阅读(174)  评论(0编辑  收藏  举报