ABC 354 (atcoder beginer 354) D、E、F 详细题解

 

D

 

检查:

1. 有可能是推导式有问题,比如-/+写错

2. x,y A、B、C、D 顺序可能搞反了

不要盲目调试,先用人眼看一下代码的情况,找一下错误

 

很简单的找规律的题目。

很不能理解过的人,就这些。

x方向,y方向,都是4行/列,一个规律的循环。

 

求(0,0)到(x,y)中的黑色块:

第0-3行分别求出黑色块数目:通过列的循环

然后行的循环求和

 

 

cal(C,D) - cal(A,D) - cal(C,B) + cal(A,B) 这个很熟悉吧。就是:

 

为了方便求,先把x、y坐标的数值都转为正整数。

 

  1 /*
  2 检查;
  3 1. 有可能是推导式有问题,比如-/+写错
  4 2. x,y   A、B、C、D 顺序可能搞反了
  5 不要盲目调试,先用人眼看一下代码的情况,找一下错误
  6 */
  7 #include <cstdio>
  8 #include <cstdlib>
  9 #include <cstring>
 10 #include <cmath>
 11 #include <cstdbool>
 12 #include <string>
 13 #include <algorithm>
 14 #include <iostream>
 15 #include <sstream>
 16 #include <ctime>
 17 #include <stack>
 18 #include <vector>
 19 #include <queue>
 20 #include <set>
 21 #include <map>
 22 #include <array>
 23 #include <bitset>
 24 using namespace std;
 25 #define LL long long
 26 #define ULL unsigned long long
 27 
 28 const LL mod_1=1e9+7;
 29 const LL mod_2=998244353;
 30 
 31 const double eps_1=1e-5;
 32 const double eps_2=1e-10;
 33 
 34 const int maxn=2e5+10;
 35 
 36 ///x 0 to 4 : y value
 37 LL f[4][4]={
 38 {2,1,2,1},
 39 {1,2,1,2},
 40 {0,1,0,1},
 41 {1,0,1,0}
 42 };
 43 LL f_loop[4]={6,6,2,2};
 44 
 45 LL v[4];
 46 
 47 LL cal(LL x, LL y)
 48 {
 49     v[0]=v[1]=v[2]=v[3]=0;
 50 
 51     LL x_mod = x%4;
 52     LL y_mod = y%4;
 53     LL x_loop = x/4;
 54     LL y_loop = y/4;
 55     LL i,j,result=0;
 56 
 57     for (i=0;i<4;i++)
 58         v[i]+=y_loop * f_loop[i];
 59     for (i=0;i<4;i++)
 60     {
 61         for (j=0;j<y_mod;j++)
 62             v[i]+=f[i][j];
 63     }
 64     LL f_loop_cnt=v[0]+v[1]+v[2]+v[3];
 65 
 66     result += f_loop_cnt * x_loop;
 67 
 68     for (i=0;i<x_mod;i++)
 69         result+=v[i];
 70 
 71 
 72     return result;
 73 }
 74 
 75 int main()
 76 {
 77     LL A,B,C,D,temp;
 78 
 79     if (0)
 80     {
 81         /*
 82         cout<<cal(1,1)<<endl;
 83         cout<<cal(2,2)<<endl;
 84         cout<<cal(3,3)<<endl;
 85         cout<<cal(4,4)<<endl;
 86         */
 87 
 88         //cout<<cal(1,2)<<endl;
 89         //cout<<cal(2,1)<<endl;
 90 
 91         //cout<<cal(1,6)<<endl;
 92 
 93         //cout<<cal(2,5)<<endl;
 94 
 95         cout<<cal(5,7)<<endl;
 96         cout<<cal(5,2)<<endl;
 97         cout<<cal(3,7)<<endl;
 98         cout<<cal(3,2)<<endl;
 99 
100 
101         return 0;
102     }
103 
104 
105     cin>>A>>B>>C>>D;
106 
107     if (A<0)
108     {
109         temp=(-A+4)/4;
110         A+=temp*4;
111         C+=temp*4;
112     }
113 
114     if (B<0)
115     {
116         temp=(-B+4)/4;
117         B+=temp*4;
118         D+=temp*4;
119     }
120 
121 
122 
123 
124 
125     cout<< cal(C,D) - cal(A,D) - cal(C,B) + cal(A,B);
126 
127     return 0;
128 }

 

 

 

E

这么多人对,有点怀疑是不是AI做的。

我用chatgpt 4-o(现在免费的),居然一发入魂,AC了。

我在CF提出了我的疑问。也看到有人跟我提出类似的疑问。

Panasonic Programming Contest 2024(AtCoder Beginner Contest 354) Announcement - Codeforces

So many people solve E in the competition. I doubt if some of them using chatgpt. I get AC of problem E using code generated by chatgpt 4o. The code is as follows.
It is more stranger that the people solve E are 2223, D are 2092. D、F are quite a lot easy compare with E. D is quite easy by the way, but only 2092 people solve it. I doubt if some of them using **chatgpt** by solving proble **E**. I get AC of problem E using code generated by chatgpt 4o.

 我倒觉得D题AC数目比E题少很不正常。D题是非常简单的模拟题。我赛后用chatgpt 4o去解答E题,获得了正确的答案。

chatgpt:甚至题目直接复制粘贴就可以了,即使有格式上的错误也可以。

重复试了两次,都能AC。

为什么会出现这样的情况?:1. 有以前类似的题目? 2 网络上的搜索功能? 3 chatgpt就是牛逼。

 

============================================

 

当然这只是怀疑。

如果想要验证?

可以爬虫代码

然后 1 找变量 2 代码相似度

 

=============================================

 

也看到别人up主的题解,AtCoder Beginner Contest 354 A 至 F 題讲解 by dreamoon_哔哩哔哩_bilibili

 

=============================================

 

 

 1 #include <iostream>
 2 #include <vector>
 3 #include <unordered_map>
 4 
 5 using namespace std;
 6 
 7 struct Card {
 8     int front;
 9     int back;
10 };
11 
12 int N;
13 vector<Card> cards;
14 unordered_map<int, bool> memo;
15 
16 bool canWin(int state) {
17     if (memo.count(state)) return memo[state];
18 
19     // Check all pairs of cards
20     for (int i = 0; i < N; ++i) {
21         if (!(state & (1 << i))) continue; // Card i is already removed
22         for (int j = i + 1; j < N; ++j) {
23             if (!(state & (1 << j))) continue; // Card j is already removed
24             if (cards[i].front == cards[j].front || cards[i].back == cards[j].back) {
25                 int newState = state & ~(1 << i) & ~(1 << j);
26                 if (!canWin(newState)) {
27                     memo[state] = true;
28                     return true;
29                 }
30             }
31         }
32     }
33     memo[state] = false;
34     return false;
35 }
36 
37 int main() {
38     cin >> N;
39     cards.resize(N);
40     for (int i = 0; i < N; ++i) {
41         cin >> cards[i].front >> cards[i].back;
42     }
43 
44     int initialState = (1 << N) - 1; // All cards are initially on the table
45     if (canWin(initialState)) {
46         cout << "Takahashi" << endl;
47     } else {
48         cout << "Aoki" << endl;
49     }
50 
51     return 0;
52 }

 

 

=========================================================================

=========================================================================

=========================================================================

 

 

18这个数字,想到2^18(<1e6)复杂度?

 

 

=========================================================================

 

1. 0/1 记录这个位置的卡片是否被取走

2. 记录当前位置是否已经出现遍历过

那么总共可能出现的情况是:

C(18,2)+C(18,4)+C(18,6)+...+C(18,18) = 131071 基本上等于 2^18/2 ( = 2^18/2 -1)

 

它不会出现:第一个遍历,有C(18,2)种情况,然后第二次遍历,有C(16,2)种情况,然后C(18,2)*C(16,2)*C(14,2)*...*C(2,2) = A(18,18) / 2^9。 这样写,会超时。

 

然后复杂度乘上每次两个数的遍历,就是2^17*18*17/2(20,054,016)左右,算上bitset这些复杂度,不会超。实际上17ms。

但是判断一个状态是否出现过,不采用bitset的方式,按道理,O(n),再乘上这个,就是2^17*18*17/2*n,会超时。但是AC了,51ms…… 怪不得过的人这么多。

实际上,判断一个状态是否出现过,不采用bitset的方式,复杂度不是这样的。遍历的点,的确是2^17*18*17/2(20,054,016)。但是满足需要更新的点(d_new),数目不是这个。它是:

C(18,2)*C(16,2) + C(18,4)*C(14,2) + C(18,6)*C(12,2) + ... + C(18,16)*C(2,2) = 5013351

然后,5013351*18=90,240,318,也不会超时。当n=20,498,069,800,2s有可能超。

 

而且,实际上它造的样例,可能也不是太到极限,emmm……

 

同时,还有一个优化,就是当有一个情况满足的时候,直接退出(只需要一个情况满足就行)。这样对于特殊样例,基本都可以删除的情况下(两两基本可以进行删除),它算得很快。比如n=24,n=23那个样例。

 

 

 

特殊样例就是这个:

 1 18
 2 1 1
 3 1 1
 4 1 1
 5 1 1
 6 1 1
 7 1 1
 8 1 1
 9 1 1
10 1 1
11 1 1
12 1 1
13 1 1
14 1 1
15 1 1
16 1 1
17 1 1
18 1 1
19 1 1
20 
21 
22 ======
23 
24 6
25 1 1
26 1 1
27 1 1
28 1 1
29 1 1
30 1 1
31 
32 ======
33 
34 24
35 1 1
36 1 1
37 1 1
38 1 1
39 1 1
40 1 1
41 1 1
42 1 1
43 1 1
44 1 1
45 1 1
46 1 1
47 1 1
48 1 1
49 1 1
50 1 1
51 1 1
52 1 1
53 1 1
54 1 1
55 1 1
56 1 1
57 1 1
58 1 1
59 
60 ======
61 
62 23
63 1 1
64 1 1
65 1 1
66 1 1
67 1 1
68 1 1
69 1 1
70 1 1
71 1 1
72 1 1
73 1 1
74 1 1
75 1 1
76 1 1
77 1 1
78 1 1
79 1 1
80 1 1
81 1 1
82 1 1
83 1 1
84 1 1
85 1 1

 

 

 

 

最基础的样例

1 2
2 1 1
3 1 1
4 Takahashi
5 
6 ======
7 
8 0
9 Aoki

 

 

 

算复杂度

 1 #include <iostream>
 2 using namespace std;
 3 #define LL long long
 4 
 5 LL cal(LL d)
 6 {
 7     return d*(d-1)/2;
 8 }
 9 
10 LL C(LL a, LL b)
11 {
12     LL r=1,i;
13     for (i=a;i>a-b;i--)
14         r=r*i;
15     for (i=1;i<=b;i++)
16         r=r/i;
17     return r;
18 }
19 
20 int main()
21 {
22     LL v=0, i, n=20;//18
23     //for (i=18;i>=2;i-=2)
24     //    v+=cal(i);
25       ///525
26 
27 
28     /*
29     for (i=2;i<=18;i+=2)
30         v+=C(18,i);
31     ///131071
32     */
33 
34 
35 //    for (i=1;i<=18;i++)
36 //        v+=C(18,i);
37     ///262143
38 
39     for (i=2;i<=n;i+=2)
40         v += C(n,i) * C(n-i,2);
41 
42     cout<<v<<endl;
43     return 0;
44 }

 

用bitset,做了优化:10ms

  1 #include <cstdio>
  2 #include <cstdlib>
  3 #include <cstring>
  4 #include <cmath>
  5 #include <cstdbool>
  6 #include <string>
  7 #include <algorithm>
  8 #include <iostream>
  9 #include <sstream>
 10 #include <ctime>
 11 #include <stack>
 12 #include <vector>
 13 #include <queue>
 14 #include <set>
 15 #include <map>
 16 #include <array>
 17 #include <bitset>
 18 using namespace std;
 19 #define LL long long
 20 #define ULL unsigned long long
 21 
 22 const LL mod_1=1e9+7;
 23 const LL mod_2=998244353;
 24 
 25 const double eps_1=1e-5;
 26 const double eps_2=1e-10;
 27 
 28 const int maxn=20;
 29 const int maxm=1<<20;
 30 
 31 int n;
 32 int x[maxn], y[maxn];
 33 int vis[maxm];
 34 
 35 int dfs(int d)
 36 {
 37     int i,j,d_new;
 38     if (d==0)
 39     {
 40         vis[0]=0;
 41         return 0;
 42     }
 43     for (i=0;i<n-1;i++)
 44         //if ((d>>i) & 1)
 45         if (d & (1<<i))
 46             for (j=i+1;j<n;j++)
 47             {
 48                 d_new = d & ~(1<<i) & ~(1<<j);
 49                 if ((d & (1<<j)) && (x[i]==x[j] || y[i]==y[j]))
 50                 {
 51                     if (vis[d_new]==-1)
 52                         dfs(d_new);
 53 
 54 
 55                     if (vis[d_new]==0)
 56                     {
 57                         vis[d]=1;
 58                         return 1;
 59                     }
 60                 }
 61             }
 62     vis[d]=0;
 63     return 0;
 64 }
 65 
 66 int main()
 67 {
 68     int i;
 69     memset(vis,0xff,sizeof(vis));
 70     scanf("%d",&n);
 71     for (i=0;i<n;i++)
 72         scanf("%d%d",&x[i],&y[i]);
 73 
 74     if (dfs((1<<n)-1))
 75         printf("Takahashi\n");
 76     else
 77         printf("Aoki\n");      ///n=0 Aoki
 78 
 79     return 0;
 80 }
 81 /*
 82 2
 83 1 1
 84 1 1
 85 Takahashi
 86 
 87 ======
 88 
 89 0
 90 Aoki
 91 
 92 ======
 93 
 94 4
 95 1 1
 96 1 1
 97 1 1
 98 1 1
 99 Aoki
100 
101 ======
102 
103 3
104 1 9
105 4 9
106 1 4
107 
108 ======
109 
110 3
111 2 5
112 1 4
113 2 5
114 */

 

 

用bitset,没做优化:51ms

  1 #include <cstdio>
  2 #include <cstdlib>
  3 #include <cstring>
  4 #include <cmath>
  5 #include <cstdbool>
  6 #include <string>
  7 #include <algorithm>
  8 #include <iostream>
  9 #include <sstream>
 10 #include <ctime>
 11 #include <stack>
 12 #include <vector>
 13 #include <queue>
 14 #include <set>
 15 #include <map>
 16 #include <array>
 17 #include <bitset>
 18 using namespace std;
 19 #define LL long long
 20 #define ULL unsigned long long
 21 
 22 const LL mod_1=1e9+7;
 23 const LL mod_2=998244353;
 24 
 25 const double eps_1=1e-5;
 26 const double eps_2=1e-10;
 27 
 28 const int maxn=20;
 29 const int maxm=1<<20;
 30 
 31 int n;
 32 int x[maxn], y[maxn];
 33 int vis[maxm];
 34 
 35 int dfs(int d)
 36 {
 37     int i,j,d_new, r=0;
 38     if (d==0)
 39     {
 40         vis[0]=0;
 41         return 0;
 42     }
 43     for (i=0;i<n-1;i++)
 44         //if ((d>>i) & 1)
 45         if (d & (1<<i))
 46             for (j=i+1;j<n;j++)
 47             {
 48                 d_new = d & ~(1<<i) & ~(1<<j);
 49                 if ((d & (1<<j)) && (x[i]==x[j] || y[i]==y[j]))
 50                 {
 51                     if (vis[d_new]==-1)
 52                         dfs(d_new);
 53 
 54                     r |= (vis[d_new] ^ 1);
 55                 }
 56             }
 57     vis[d]=r;
 58     return r;
 59 }
 60 
 61 int main()
 62 {
 63     int i;
 64     memset(vis,0xff,sizeof(vis));
 65     scanf("%d",&n);
 66     for (i=0;i<n;i++)
 67         scanf("%d%d",&x[i],&y[i]);
 68 
 69     if (dfs((1<<n)-1))
 70         printf("Takahashi\n");
 71     else
 72         printf("Aoki\n");      ///n=0 Aoki
 73 
 74     return 0;
 75 }
 76 /*
 77 2
 78 1 1
 79 1 1
 80 Takahashi
 81 
 82 ======
 83 
 84 0
 85 Aoki
 86 
 87 ======
 88 
 89 4
 90 1 1
 91 1 1
 92 1 1
 93 1 1
 94 Aoki
 95 
 96 ======
 97 
 98 3
 99 1 9
100 4 9
101 1 4
102 
103 ======
104 
105 3
106 2 5
107 1 4
108 2 5
109 */

 

 

 

 

没有用bitset,做了优化的:66ms

  1 #include <cstdio>
  2 #include <cstdlib>
  3 #include <cstring>
  4 #include <cmath>
  5 #include <cstdbool>
  6 #include <string>
  7 #include <algorithm>
  8 #include <iostream>
  9 #include <sstream>
 10 #include <ctime>
 11 #include <stack>
 12 #include <vector>
 13 #include <queue>
 14 #include <set>
 15 #include <map>
 16 #include <array>
 17 #include <bitset>
 18 using namespace std;
 19 #define LL long long
 20 #define ULL unsigned long long
 21 
 22 const LL mod_1=1e9+7;
 23 const LL mod_2=998244353;
 24 
 25 const double eps_1=1e-5;
 26 const double eps_2=1e-10;
 27 
 28 const int maxn=25;
 29 const int maxm=1<<25;
 30 
 31 int n;
 32 int x[maxn], y[maxn];
 33 int vis[maxm];
 34 
 35 bool use[maxn];
 36 
 37 LL cnt_bianli=0, cnt_bianli_d=0;
 38 
 39 int dfs(int d)
 40 {
 41     int i,j,d_new, r=0, k;
 42     if (d==0)
 43     {
 44         vis[0]=0;
 45         return 0;
 46     }
 47 
 48     cnt_bianli_d++;
 49 
 50     for (i=0;i<n-1;i++)
 51         if (use[i])
 52             for (j=i+1;j<n;j++)
 53                 if (use[j] && (x[i]==x[j] || y[i]==y[j]))
 54                 {
 55                     cnt_bianli++;
 56 
 57                     use[i]=0;
 58                     use[j]=0;
 59 
 60                     d_new=0;
 61                     for (k=0;k<n;k++)
 62                         d_new+=use[k]*(1<<k);
 63                     if (vis[d_new]==-1)
 64                         dfs(d_new);
 65 
 66                     r |= (vis[d_new] ^ 1);
 67 
 68                     use[i]=1;
 69                     use[j]=1;
 70 
 71                     ///add
 72 
 73                     if (r==1)
 74                     {
 75                         vis[d]=1;
 76                         return 1;
 77                     }
 78 
 79 
 80                 }
 81 
 82     vis[d]=r;
 83     return r;
 84 }
 85 
 86 int main()
 87 {
 88     int i;
 89     memset(vis,0xff,sizeof(vis));
 90     scanf("%d",&n);
 91     for (i=0;i<n;i++)
 92         scanf("%d%d",&x[i],&y[i]);
 93 
 94     memset(use,1,sizeof(use));  ///1
 95     if (dfs((1<<n)-1))
 96         printf("Takahashi\n");
 97     else
 98         printf("Aoki\n");      ///n=0 Aoki
 99 
100     //cout<<"cnt_bianli "<<cnt_bianli<<endl;
101 
102     //cout<<"cnt_bianli_d "<<cnt_bianli_d*n*(n-1)/2<<endl;
103 
104     return 0;
105 }
106 /*
107 2
108 1 1
109 1 1
110 Takahashi
111 
112 ======
113 
114 0
115 Aoki
116 
117 ======
118 
119 4
120 1 1
121 1 1
122 1 1
123 1 1
124 Aoki
125 
126 ======
127 
128 3
129 1 9
130 4 9
131 1 4
132 
133 ======
134 
135 3
136 2 5
137 1 4
138 2 5
139 
140 
141 
142 
143 
144 
145 
146 
147 
148 
149 ======
150 
151 18
152 1 1
153 1 1
154 1 1
155 1 1
156 1 1
157 1 1
158 1 1
159 1 1
160 1 1
161 1 1
162 1 1
163 1 1
164 1 1
165 1 1
166 1 1
167 1 1
168 1 1
169 1 1
170 
171 
172 ======
173 
174 6
175 1 1
176 1 1
177 1 1
178 1 1
179 1 1
180 1 1
181 
182 ======
183 
184 24
185 1 1
186 1 1
187 1 1
188 1 1
189 1 1
190 1 1
191 1 1
192 1 1
193 1 1
194 1 1
195 1 1
196 1 1
197 1 1
198 1 1
199 1 1
200 1 1
201 1 1
202 1 1
203 1 1
204 1 1
205 1 1
206 1 1
207 1 1
208 1 1
209 
210 ======
211 
212 23
213 1 1
214 1 1
215 1 1
216 1 1
217 1 1
218 1 1
219 1 1
220 1 1
221 1 1
222 1 1
223 1 1
224 1 1
225 1 1
226 1 1
227 1 1
228 1 1
229 1 1
230 1 1
231 1 1
232 1 1
233 1 1
234 1 1
235 1 1
236 
237 */

 

 

没有用bitset,同时也没有做优化的:151ms

  1 #include <cstdio>
  2 #include <cstdlib>
  3 #include <cstring>
  4 #include <cmath>
  5 #include <cstdbool>
  6 #include <string>
  7 #include <algorithm>
  8 #include <iostream>
  9 #include <sstream>
 10 #include <ctime>
 11 #include <stack>
 12 #include <vector>
 13 #include <queue>
 14 #include <set>
 15 #include <map>
 16 #include <array>
 17 #include <bitset>
 18 using namespace std;
 19 #define LL long long
 20 #define ULL unsigned long long
 21 
 22 const LL mod_1=1e9+7;
 23 const LL mod_2=998244353;
 24 
 25 const double eps_1=1e-5;
 26 const double eps_2=1e-10;
 27 
 28 const int maxn=20;
 29 const int maxm=1<<20;
 30 
 31 int n;
 32 int x[maxn], y[maxn];
 33 int vis[maxm];
 34 
 35 bool use[maxn];
 36 
 37 LL cnt_bianli=0, cnt_bianli_d=0;
 38 
 39 int dfs(int d)
 40 {
 41     int i,j,d_new, r=0, k;
 42     if (d==0)
 43     {
 44         vis[0]=0;
 45         return 0;
 46     }
 47 
 48     cnt_bianli_d++;
 49 
 50     for (i=0;i<n-1;i++)
 51         if (use[i])
 52             for (j=i+1;j<n;j++)
 53                 if (use[j] && (x[i]==x[j] || y[i]==y[j]))
 54                 {
 55                     cnt_bianli++;
 56 
 57                     use[i]=0;
 58                     use[j]=0;
 59 
 60                     d_new=0;
 61                     for (k=0;k<n;k++)
 62                         d_new+=use[k]*(1<<k);
 63                     if (vis[d_new]==-1)
 64                         dfs(d_new);
 65 
 66                     r |= (vis[d_new] ^ 1);
 67 
 68                     use[i]=1;
 69                     use[j]=1;
 70                 }
 71 
 72     vis[d]=r;
 73     return r;
 74 }
 75 
 76 int main()
 77 {
 78     int i;
 79     memset(vis,0xff,sizeof(vis));
 80     scanf("%d",&n);
 81     for (i=0;i<n;i++)
 82         scanf("%d%d",&x[i],&y[i]);
 83 
 84     memset(use,1,sizeof(use));  ///1
 85     if (dfs((1<<n)-1))
 86         printf("Takahashi\n");
 87     else
 88         printf("Aoki\n");      ///n=0 Aoki
 89 
 90     cout<<"cnt_bianli "<<cnt_bianli<<endl;
 91 
 92     cout<<"cnt_bianli_d "<<cnt_bianli_d*n*(n-1)/2<<endl;
 93 
 94     return 0;
 95 }
 96 /*
 97 2
 98 1 1
 99 1 1
100 Takahashi
101 
102 ======
103 
104 0
105 Aoki
106 
107 ======
108 
109 4
110 1 1
111 1 1
112 1 1
113 1 1
114 Aoki
115 
116 ======
117 
118 3
119 1 9
120 4 9
121 1 4
122 
123 ======
124 
125 3
126 2 5
127 1 4
128 2 5
129 
130 
131 
132 
133 
134 
135 
136 
137 
138 
139 ======
140 
141 18
142 1 1
143 1 1
144 1 1
145 1 1
146 1 1
147 1 1
148 1 1
149 1 1
150 1 1
151 1 1
152 1 1
153 1 1
154 1 1
155 1 1
156 1 1
157 1 1
158 1 1
159 1 1
160 
161 
162 ======
163 
164 6
165 1 1
166 1 1
167 1 1
168 1 1
169 1 1
170 1 1
171 */

 

 

 

 

 

F

看题/做题顺序:

a. E没有什么想法的话,这种题(如果)难做,而且时间耗在那,比如先做其它题目

b. 应该先看一下F题的题意的,也许比E好做呢?

c. 特别是1000人做对,就知道题目可能相对容易做,更加需要在第40分钟-第1小时的时候,花5分钟,看一下题意

d. 如果留30-40分钟做这道题,那么会很舒服,大概率能做出来。

 

从第1位置到第x位置递增,LIS的长度,从第n位置到第x位置递减,LIS的长度,相加,如果是对的,它就可以用

 

 

因为T<=2e5,a[i]<=1e9,LIS的树状数组写法应该是很不好写的。

那么用二分的写法。

善用lower_bound很重要。

对于反过来求从大到小的LIS,数值改为相反的负值就行了,即相当于求从小到大的LIS->代码设计上的巧妙。

 

这个例子,说明用lower_bound(>=),而不是upper_bound(>)。

1 10
2 9
3 2 3 4 1 1 1 5 6 7

 

 

  1 /*
  2 题解:从第1位置到第x位置递增,LIS的长度,从第n位置到第x位置递减,LIS的长度,相加,如果是对的,它就可以用
  3 */
  4 #include <cstdio>
  5 #include <cstdlib>
  6 #include <cstring>
  7 #include <cmath>
  8 #include <cstdbool>
  9 #include <string>
 10 #include <algorithm>
 11 #include <iostream>
 12 #include <sstream>
 13 #include <ctime>
 14 #include <stack>
 15 #include <vector>
 16 #include <queue>
 17 #include <set>
 18 #include <map>
 19 #include <array>
 20 #include <bitset>
 21 using namespace std;
 22 #define LL long long
 23 #define ULL unsigned long long
 24 
 25 const LL mod_1=1e9+7;
 26 const LL mod_2=998244353;
 27 
 28 const double eps_1=1e-5;
 29 const double eps_2=1e-10;
 30 
 31 const int maxn=2e5+10;
 32 
 33 int a[maxn], f[maxn], pos1[maxn], pos2[maxn];
 34 vector<int> vec;
 35 
 36 int main()
 37 {
 38     int T,n,m,cnt,u,i,j;
 39     scanf("%d",&T);
 40     while (T--)
 41     {
 42         scanf("%d",&n);
 43         for (i=0;i<n;i++)
 44             scanf("%d", &a[i]);
 45 
 46         m=0;
 47         for (i=0;i<n;i++)
 48         {
 49             j = lower_bound(f, f+m, a[i]) - f;
 50 
 51             pos1[i]=j;
 52 
 53             f[j] = a[i];
 54             if (j==m)
 55                 m++;
 56         }
 57 
 58         /*
 59         for (i=0;i<n;i++)
 60             printf("%d ", pos1[i]);
 61         printf("\n");
 62         */
 63 
 64 
 65         for (i=0;i<n;i++)
 66             a[i]=-a[i];
 67         m=0;
 68         for (i=n-1;i>=0;i--)
 69         {
 70             j = lower_bound(f, f+m, a[i]) - f;
 71 
 72             pos2[i]=j;
 73 
 74             f[j] = a[i];
 75             if (j==m)
 76                 m++;
 77         }
 78 
 79 
 80         u=0;
 81         for (i=0;i<n;i++)
 82             u = max(u, pos1[i]+pos2[i]);
 83 
 84         vec.clear();
 85         cnt=0;
 86         for (i=0;i<n;i++)
 87             if (pos1[i]+pos2[i]==u)
 88             {
 89                 cnt++;
 90                 vec.push_back(i);
 91             }
 92 
 93         printf("%d\n",cnt);
 94         for (i=0;i<cnt;i++)
 95         {
 96             printf("%d",vec[i]+1);
 97             if (i==cnt-1)
 98                 printf("\n");
 99             else
100                 printf(" ");
101         }
102 
103 
104     }
105 
106 
107 
108     return 0;
109 }
110 /*
111 10
112 5
113 1 2 3 4 5
114 5
115 1 2 3 4 5
116 5
117 5 4 3 2 1
118 5
119 1 2 3 4 5
120 5
121 1 1 1 1 1
122 5
123 1 2 3 4 5
124 
125 
126 
127 10
128 9
129 2 3 4 1 1 1 5 6 7
130 */

 

181 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 1
 
posted @ 2024-05-20 22:03  congmingyige  阅读(12)  评论(0编辑  收藏  举报