海亮游记DAY3

我。。。

自闭了。。。

今天按照惯例依旧。。。考试了

被昨天的题目暴虐以及被一些题目摁在地上摩擦之后,

我又一次的坐在了机房,拿起了键盘和鼠标玩起了小恐龙,嗯,真   香

好了,先来看一下今天的毒瘤题目:
2019/7/8
一、 题目概览
中文题目名称 三笔画 取石子 放积木
英文题目名称 3lines stone block
可执行文件名 3lines stone block
输入文件名 3lines.in stone.in block.in
输出文件名 3lines.out stone.out block.out
时间限制 1s 1s 1
空间限制 256MB 256MB 256MB
测试点数目 捆绑测试 捆绑测试 10
测试点分值 捆绑测试 捆绑测试 10
题目类型 传统 传统 传统
比较方式 全文比较 全文比较 全文比较
是否有部分分 否 否 否
二、注意事项:
1.文件名(程序名和输入输出文件名)必须使用小写。
2.C/C++中函数main()的返回值类型必须是int,程序正常结束时的返回值必须0。
3.开启 O2 优化,栈空间开大至 256M。
三笔画( 3lines)
【 题目描述】
二维平面内有 n 个不同的点, Alice 需要在平面内画至多 3 条直线使得所有点在直线上。
问: Alice 能否完成任务, 如果能, 输出”YES”; 否则, 输出”NO”。
注意: 由于 Alice 的画图水平有限, 直线只能平行于坐标轴。
【输入数据】
第一行, 一个整数 n。
接下来 n 行, 第 i+1 行包含空格隔开的整数 xi,yi,表示第 i 个点的坐标。
【输出数据】
若 Alice 能完成任务, 输出”YES”, 否则输出”NO”。
【 样例输入】
6
1 7
0 0
1 2
2 0
1 4
3 4
【样例输出】
YES
【样例解释】
三条直线分别为 x=1,y=0,y=4。
【数据范围】
对于 30%的数据, 1 <= n <= 13。
对于 60%的数据, 1 <= n <= 20。
对于 100%的数据, 1 <= n <= 5e4, 0 <= xi, yi <= 1e9。
取石子( stone)
【题目描述】
有 n 堆石子,第 i 堆有 xi 个。
Alice 和 Bob 轮流取石子(先后手未定), Alice 每次从一堆中取走 a 个, Bob 每次从一
堆中取走 b 个,无法操作者输。
不难发现只会有四种情况: Alice 必胜; Bob 必胜;先手必胜;后手必胜。
你需要选定若干堆石子(共有 2^n 种方案), Alice 和 Bob 只能在你选出的堆中取,问
以上四种情况对应的方案数。对 10^9+7 取模。
【输入数据】
第一行三个整数 n,a,b,第二行 n 个整数 x1~xn。
【输出数据】
一行四个整数,分别表示 Alice 必胜、 Bob 必胜、先手必胜和后手必胜的方案数,对
10^9+7 取模。
【样例输入】
2 2 3
2 3
【样例输出】
2 0 1 1
【样例解释】
选定空集时后手必胜, 选定{2}时 Alice 必胜, 选定{3}时先手必胜, 选定{2,3}时 Alice 必胜。
【数据范围】
对于 10%的数据, n, xi <= 5。
对于 50%的数据, n <= 20。
对于另外 10%的数据, a = b。
对于又另外 20%的数据, a = 1。
对于 100%的数据, 1 <= n <= 1e5, 1 <= a, b, xi <= 1e9。
放积木(block)
【问题描述】
Alice 有 n 块积木,放置第 i 块积木会占据区间[Li, Ri]。
Alice 每次会腾出一个区间放积木,她希望放的积木尽可能多,对每个询问区间,你需
要回答 Alice 最多可放置的积木数量。
注意: 积木与积木的放置区间不可重叠,且任意选定的积木放置区间不能超出询问区间。
【输入格式】
第一行三个整数 n,q,len,表示积木的数量,询问数和 len 的大小(数据保证 1≤Li,Ri≤
len) 。
接下来 n 行,每行两个整数 Li,Ri, 表示积木占据的区间。
接下来 q 行,每行两个整数 ai,bi, 表示询问区间。
【输出格式】
对于每组询问输出对应的答案。
【输入样例】
3 2 4
1 2
2 3
3 4
1 3
3 3

T1:

说实话,这道题,真的只是一道模拟题(我最近对模拟有点上火,所以我要模拟退下火,,,

因为只有3条边,而且只有x,y两条边,所以就算码量最大的纯模拟也只有8种情况

 

  1 #include<bits/stdc++.h>
  2 using namespace std;
  3 template <typename type>
  4 void scan(type &x){
  5     type f=1;x=0;char s=getchar();
  6     while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
  7     while(s>='0'&&s<='9'){x=x*10+s-'0';s=getchar();}
  8     x*=f;
  9 }
 10 const int maxn=5e4+7;
 11 struct node{
 12     int x,y;
 13 }a[50007];
 14 int n;
 15 map<int,int>xx;
 16 map<int,int>yy;
 17 //map<int,int>visx;
 18 //map<int,int>visy;
 19 int maxx1,maxx2,k1,k2;
 20 //int mx,my;
 21 int main(){
 22     freopen("3lines.in","r",stdin);
 23     freopen("3lines.out","w",stdout);
 24     scan(n);
 25     for(int i=1;i<=n;i++){
 26         scan(a[i].x);
 27         xx[a[i].x]++;
 28         if(maxx1<xx[a[i].x]){
 29             k1=a[i].x;
 30             maxx1=xx[a[i].x];
 31         }
 32 //        mx=max(mx,a[i].x);
 33         scan(a[i].y);
 34         yy[a[i].y]++;
 35         if(maxx2<yy[a[i].y]){
 36             k2=a[i].y;
 37             maxx2=yy[a[i].y];
 38         }
 39 //        my=max(my,a[i].y);
 40     }
 41     if(maxx1>maxx2){
 42         for(int i=1;i<=n;i++){
 43             if(a[i].x==k1){
 44                 yy[a[i].y]--;
 45                 xx[a[i].x]--;
 46             }
 47         }//加第一条边 x
 48         maxx1=0,maxx2=0;
 49         for(int i=1;i<=n;i++){
 50 //            if(visx[a[i].x]==0){
 51                 if(maxx1<xx[a[i].x]){
 52                     maxx1=xx[a[i].x];
 53                     k1=a[i].x;
 54                 }
 55 //                visx[a[i].x]++;
 56 //            }
 57 //            if(visy[a[i].y]==0){
 58                 if(maxx2<yy[a[i].y]){
 59                     maxx2=yy[a[i].y];
 60                     k2=a[i].y;
 61                 }
 62 //                visy[a[i].y]++;
 63 //            }
 64         }
 65         if(maxx1==0||maxx2==0){printf("YES");return 0;}//x
 66         if(maxx1>maxx2){
 67         for(int i=1;i<=n;i++){
 68             if(a[i].x==k1){
 69                 yy[a[i].y]--;
 70                 xx[a[i].x]--;
 71             }
 72         }//加第2条边 x
 73         maxx1=0,maxx2=0;
 74         for(int i=1;i<=n;i++){
 75 //            if(visx[a[i].x]==1){
 76                 if(maxx1<xx[a[i].x]){
 77                     maxx1=xx[a[i].x];
 78                     k1=a[i].x;
 79                 }
 80 //                visx[a[i].x]++;
 81 //            }
 82 //            if(visy[a[i].y]==1){
 83                 if(maxx2<yy[a[i].y]){
 84                     maxx2=yy[a[i].y];
 85                     k2=a[i].y;
 86                 }
 87 //                visy[a[i].y]++;
 88 //            }
 89         }
 90         if(maxx1==0||maxx2==0){printf("YES");return 0;}//xx
 91         if(maxx1>maxx2){
 92         for(int i=1;i<=n;i++){
 93             if(a[i].x==k1){
 94                 yy[a[i].y]--;
 95                 xx[a[i].x]--;
 96             }
 97         }//加第3条边x 
 98         for(int i=1;i<=n;i++){
 99             if(xx[a[i].x]>0||yy[a[i].y]>0){printf("NO");return 0;}
100         }
101         printf("YES");return 0;//xxx
102     }else
103     {
104         for(int i=1;i<=n;i++){
105             if(a[i].y==k2){
106                 xx[a[i].x]--;
107                 yy[a[i].y]--;
108             }
109         }//3y
110         for(int i=1;i<=n;i++){
111             if(xx[a[i].x]>0||yy[a[i].y]>0){printf("NO");return 0;}
112         }
113         printf("YES");return 0;//xxy
114     }
115     }else{
116         for(int i=1;i<=n;i++){
117             if(a[i].y==k2){
118                 xx[a[i].x]--;
119                 yy[a[i].y]--;
120             }
121         }//2y
122         maxx1=0,maxx2=0;
123         for(int i=1;i<=n;i++){
124 //            if(visx[a[i].x]==1){
125                 if(maxx1<xx[a[i].x]){
126                     maxx1=xx[a[i].x];
127                     k1=a[i].x;
128                 }
129 //                visx[a[i].x]++;
130 //            }
131 //            if(visy[a[i].y]==1){
132                 if(maxx2<yy[a[i].y]){
133                     maxx2=yy[a[i].y];
134                     k2=a[i].y;
135                 }
136 //                visy[a[i].y]++;
137 //            }
138         }
139         if(maxx1==0||maxx2==0){printf("YES");return 0;}//xy
140         if(maxx1>maxx2){
141         for(int i=1;i<=n;i++){
142             if(a[i].x==k1){
143                 yy[a[i].y]--;
144                 xx[a[i].x]--;
145             }
146         }
147         for(int i=1;i<=n;i++){
148             if(xx[a[i].x]>0||yy[a[i].y]>0){printf("NO");return 0;}
149         }
150         printf("YES");return 0;//xyx
151     }else{
152         for(int i=1;i<=n;i++){
153             if(a[i].y==k2){
154                 xx[a[i].x]--;
155                 yy[a[i].y]--;
156             }
157         }//3y
158         for(int i=1;i<=n;i++){
159             if(xx[a[i].x]>0||yy[a[i].y]>0){printf("NO");return 0;}
160         }
161         printf("YES");return 0;//xyy
162     }
163     }}else{
164         for(int i=1;i<=n;i++){
165             if(a[i].y==k2){
166                 xx[a[i].x]--;
167                 yy[a[i].y]--;
168             }
169         }//1y
170         maxx1=0,maxx2=0;
171         for(int i=1;i<=n;i++){
172 //            if(visx[a[i].x]==0){
173                 if(maxx1<xx[a[i].x]){
174                     maxx1=xx[a[i].x];
175                     k1=a[i].x;
176                 }
177 //                visx[a[i].x]++;
178 //            }
179 //            if(visy[a[i].y]==0){
180                 if(maxx2<yy[a[i].y]){
181                     maxx2=yy[a[i].y];
182                     k2=a[i].y;
183                 }
184 //                visy[a[i].y]++;
185 //            }
186         }
187         if(maxx1==0||maxx2==0){printf("YES");return 0;}//y
188         if(maxx1>maxx2){
189             for(int i=1;i<=n;i++){
190             if(a[i].x==k1){
191                 yy[a[i].y]--;
192                 xx[a[i].x]--;
193             }
194         }//加第2条边 x
195         maxx1=0,maxx2=0;
196         for(int i=1;i<=n;i++){
197 //            if(visx[a[i].x]==1){
198                 if(maxx1<xx[a[i].x]){
199                     maxx1=xx[a[i].x];
200                     k1=a[i].x;
201                 }
202 //                visx[a[i].x]++;
203 //            }
204 //            if(visy[a[i].y]==1){
205                 if(maxx2<yy[a[i].y]){
206                     maxx2=yy[a[i].y];
207                     k2=a[i].y;
208                 }
209 //                visy[a[i].y]++;
210 //            }
211         }
212         if(maxx1==0||maxx2==0){printf("YES");return 0;}//yx
213         if(maxx1>maxx2){
214             for(int i=1;i<=n;i++){
215             if(a[i].x==k1){
216                 yy[a[i].y]--;
217                 xx[a[i].x]--;
218             }
219         }//加第3条边x 
220         for(int i=1;i<=n;i++){
221             if(xx[a[i].x]>0||yy[a[i].y]>0){printf("NO");return 0;}
222         }
223         printf("YES");return 0;//yxx
224         }else{
225             for(int i=1;i<=n;i++){
226             if(a[i].y==k2){
227                 xx[a[i].x]--;
228                 yy[a[i].y]--;
229             }
230         }//3y
231         for(int i=1;i<=n;i++){
232             if(xx[a[i].x]>0||yy[a[i].y]>0){printf("NO");return 0;}
233         }
234         printf("YES");return 0;//yxy
235         }
236         }else{
237             for(int i=1;i<=n;i++){
238             if(a[i].y==k2){
239                 xx[a[i].x]--;
240                 yy[a[i].y]--;
241             }
242         }//2y
243         maxx1=0,maxx2=0;
244         for(int i=1;i<=n;i++){
245 //            if(visx[a[i].x]==1){
246                 if(maxx1<xx[a[i].x]){
247                     maxx1=xx[a[i].x];
248                     k1=a[i].x;
249                 }
250 //                visx[a[i].x]++;
251 //            }
252 //            if(visy[a[i].y]==1){
253                 if(maxx2<yy[a[i].y]){
254                     maxx2=yy[a[i].y];
255                     k2=a[i].y;
256                 }
257 //                visy[a[i].y]++;
258 //            }
259         }
260         if(maxx1==0||maxx2==0){printf("YES");return 0;}//yy
261         if(maxx1>maxx2){
262             for(int i=1;i<=n;i++){
263             if(a[i].x==k1){
264                 yy[a[i].y]--;
265                 xx[a[i].x]--;
266             }
267         }//加第3条边x 
268         for(int i=1;i<=n;i++){
269             if(xx[a[i].x]>0||yy[a[i].y]>0){printf("NO");return 0;}
270         }
271         printf("YES");return 0;//yyx
272         }else{
273             for(int i=1;i<=n;i++){
274             if(a[i].y==k2){
275                 xx[a[i].x]--;
276                 yy[a[i].y]--;
277             }
278         }//3y
279         for(int i=1;i<=n;i++){
280             if(xx[a[i].x]>0||yy[a[i].y]>0){printf("NO");return 0;}
281         }
282         printf("YES");return 0;//yyy
283         }
284         }
285     }
286 
287     return 0;
288 }
我的288行暴力代码qwq

 

对于正解来说,就是将有些不必要的情况去掉,

考虑这三条直线的状态,只可能为
(1)三条水平线
(2)两条水平线+一条垂直线
(剩余情况交换 x,y 坐标即可)
我们用一个数组统计同一 y 坐标上有几个点。
对于 1)的情况,只需判断是否只有三个及以下的 y 坐标上有点即可。
对于 2)的情况,可以枚举垂直线的 x 坐标,将这条垂直线上的点全部删去,判断剩下的
点的 y 坐标是否只有两种及以下。
将点按 x 坐标排序后即可做到 O(n)的扫描。

 

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 using namespace std;
 5 int n;
 6 struct point{
 7     int x,y;
 8 }a[50001];
 9 int xx[50001];
10 int yy[50001];
11 int sum[50001];
12 int fx,fy;
13 int read(){
14     scanf("%d",&n);
15     for (int i=1;i<=n;++i){
16         scanf("%d%d",&xx[i],&yy[i]);
17         a[i].x=xx[i];
18         a[i].y=yy[i];        
19     }   
20     sort(xx+1,xx+n+1);
21     sort(yy+1,yy+n+1);
22     fx=unique(xx+1,xx+n+1)-xx-1;
23     fy=unique(yy+1,yy+n+1)-yy-1;
24     for (int i=1;i<=n;++i){
25         a[i].x=lower_bound(xx+1,xx+fx+1,a[i].x)-xx;
26         a[i].y=lower_bound(yy+1,yy+fy+1,a[i].y)-yy;
27     }
28 }
29 int cmp(const point &a,const point &b){
30     return a.x<b.x?1:((a.x==b.x)&&(a.y<b.y));
31 }
32 int work(){
33     int tot=0;
34     sort(a+1,a+n+1,cmp);    
35     for (int i=1;i<=n;++i)
36         if (sum[a[i].y]++==0)++tot;
37     if (tot<=3)return 1;
38     int t=1,w;
39     while (t<=n){
40         w=t;
41         while (w<n&&a[w+1].x==a[t].x)++w;
42         for (int i=t;i<=w;++i)
43             if (sum[a[i].y]--==1)--tot;
44         if (tot<=2)return true;
45         for (int i=t;i<=w;++i)
46             if (sum[a[i].y]++==0)++tot;
47         t=w+1;
48     }
49     return 0;
50 }
51 int main(){
52     freopen("3lines.in","r",stdin);
53     freopen("3lines.out","w",stdout);
54     read();
55     if (work()){
56         puts("YES");
57     }
58     else {
59         memset(sum,0,sizeof(sum));
60         for (int i=1;i<=n;++i)
61             swap(a[i].x,a[i].y);
62         puts(work()? "YES" : "NO");
63     }
64     fclose(stdin);
65     fclose(stdout);
66 }
std

 

T2:

是一道博弈论,但是我没有学过啊QWQ,但是在情况的讨论中还是十分清晰。

下面为分析过程:
不妨假设a < b。
每堆石子先对a + b取模,然后可以分为4种:
(1)xi < a,没用。
(2)a <= xi < b,只要存在则a必胜。
(3)b <= xi < 2a,只和奇偶性有关。
(4)2a <= xi, 存在至少2个则a必胜, 存在1个且(3)为偶数则先手必胜, 存在1个且(3)为奇
数则a必胜, 不存在且(3)为奇数则先手必胜, 不存在且(3)为偶数则后手必胜。
时间复杂度 O(n)

 1 #include <cstdio>
 2 #include <iostream>
 3 #include <algorithm>
 4 typedef long long ll;
 5 inline int Get() {
 6     char ch;
 7     while ((ch = getchar()) < '0' || ch > '9');
 8     int Num = ch - '0';
 9     while ((ch = getchar()) >= '0' && ch <= '9')
10         Num = (Num << 3) + (Num << 1) + ch - '0';
11     return Num;
12 }
13 const int Mod = 1e9 + 7;
14 const int N = 1e5 + 5;
15 int n, A, B, x[N], n1, n2, n3, n4, former, latter, mner, g[N][2];
16 inline int pow(int x, int k) {
17     ll res = 1, r = x;
18     for (; k; k >>= 1, r = r * r % Mod)
19         if (k & 1) res = res * r % Mod;
20     return res;
21 }
22 int main() {
23     freopen("stone.in", "r", stdin);
24     freopen("stone.out", "w", stdout);
25     n = Get(), A = Get(), B = Get();
26     for (int i = 1; i <= n; ++i) x[i] = Get();
27     
28     if (A == B) {
29         for (int i = 1; i <= n; ++i) x[i] /= A;
30         
31         g[0][0] = 1;
32         for (int i = 1; i <= n; ++i) {
33             int c = x[i] & 1;
34             g[i][0] = (g[i - 1][0] + g[i - 1][c ^ 0]) % Mod;
35             g[i][1] = (g[i - 1][1] + g[i - 1][c ^ 1]) % Mod;
36         }
37         
38         printf("0 0 %d %d\n", g[n][1], g[n][0]);
39         return 0;
40     }
41     
42     for (int i = 1; i <= n; ++i) x[i] %= (A + B);
43     int mn = std :: min(A, B), mx = std :: max(A, B);
44     
45     for (int i = 1; i <= n; ++i) 
46         n1 += (x[i] < mn), n2 += (mn <= x[i] && x[i] < mx), n3 += (mx <= x[i] && x[i] < 2 * mn), n4 += (2 * mn <= x[i] && mx <= x[i]);    
47     
48     mner = (ll)(pow(2, n2) - 1) * pow(2, n1 + n3 + n4) % Mod;
49     if (mner < 0) mner += Mod;
50     
51     g[0][0] = 1;
52     for (int i = 1; i <= n3; ++i) {
53         g[i][0] = (g[i - 1][0] + g[i - 1][1]) % Mod;
54         g[i][1] = (g[i - 1][1] + g[i - 1][0]) % Mod;
55     }
56     
57     former = (ll)pow(2, n1) * g[n3][1] % Mod;
58     latter = (ll)pow(2, n1) * g[n3][0] % Mod;
59     
60     int total1 = n4, total2 = pow(2, n4) - n4 - 1;
61     if (total2 < 0) total2 += Mod;
62     
63     mner = ((ll)total2 * pow(2, n1 + n3) % Mod + (ll)total1 * pow(2, n1) % Mod * g[n3][1] % Mod + mner) % Mod;
64     former = ((ll)total1 * pow(2, n1) % Mod * g[n3][0] % Mod + former) % Mod; 
65     if (A < B) printf("%d 0 %d %d\n", mner, former, latter);
66     else printf("0 %d %d %d\n", mner, former, latter);
67     fclose(stdin);
68     fclose(stdout);
69     return 0;
70 }
std

 

T3:

其实这道题与我们昨天讲到的一道题十分相似(CF1175E Minimal Segment Cover),但是因为时间原因所以没有写,然后自己写的贪心暴力还写挂了。。。

 

 1 #include<cstdio>
 2 int N,Q,len;
 3 int f[100010][20];
 4 int min(int a,int b){
 5     return a<b?a:b;
 6 }
 7 int read(){
 8     scanf("%d%d%d",&N,&Q,&len);
 9     for (int i=1;i<=len+2;++i)
10         for (int j=0;j<=16;++j)
11             f[i][j]=len+1;
12 
13     for (int i=1;i<=N;++i){
14         int a,b;
15         scanf("%d%d",&a,&b);
16         f[a][0]=min(f[a][0],b);
17     }
18 }
19 int work(){
20     for (int i=len+1;i>=1;--i)
21         f[i][0]=min(f[i][0],f[i+1][0]);
22     for (int j=1;j<=16;++j)
23        for (int i=len;i>=1;--i)
24            f[i][j]=min(f[i+1][j],f[f[i][j-1]+1][j-1]);
25 }
26 int ff(int a,int b){
27     int ans=0;
28     for (int i=16;i>=0;--i)
29         if (f[a][i]<=b){
30             ans+=1<<i;
31             a=f[a][i]+1;
32         }
33     return ans;
34 }
35 int answer(){
36     for (int i=1;i<=Q;++i){
37         int a,b;
38         scanf("%d%d",&a,&b);
39         printf("%d\n",ff(a,b));
40     } 
41 }
42 int main(){
43     freopen("block.in","r",stdin);
44     freopen("block.out","w",stdout);
45     read();
46     work();
47     answer();    
48     fclose(stdin);
49     fclose(stdout);
50 } 
std

 

posted @ 2019-07-08 21:37  惜时如金  阅读(265)  评论(0编辑  收藏  举报