我。。。
自闭了。。。
今天按照惯例依旧。。。考试了
被昨天的题目暴虐以及被一些题目摁在地上摩擦之后,
我又一次的坐在了机房,拿起了键盘和鼠标玩起了小恐龙,嗯,真 香
好了,先来看一下今天的毒瘤题目:
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 }
对于正解来说,就是将有些不必要的情况去掉,
考虑这三条直线的状态,只可能为
(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 }
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 }
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 }