2017-10-01清北模拟赛
P97
zhx
: 竞赛时间:???? 年?? 月?? 日??:??-??:??
题目名称 a b c
名称 a b c
输入 a.in b.in c.in
输出 a.out b.out c.out
每个测试点时限 1s 1s 1s
内存限制 256MB 256MB 256MB
测试点数目 10 80 10
每个测试点分值 10 1 或 2 10
是否有部分分 无 无 无
题目类型 传统 传统 传统
注意 事项) (请务必仔细阅读) :
P97 zhxa
第 2 页 共 5 页
T1 a
【问题描述】
你是能看到第一题的 friends 呢。
——hja
何大爷对字符串十分有研究,于是天天出字符串题虐杀 zhx。何大爷今天为
字符串定义了新的权值计算方法。一个字符串由小写字母组成,字符串的权值
被定义为其中出现次数最多的字符的次数减去出现次数最少的字符的次数。 (注
意,在讨论出现最少的字符的时候,该字符必须至少出现一次)现在何大爷给
你一个字符串,何大爷想知道这个字符串的所有子串中权值最大的权值是多
少?
【输入格式】
第一行一个整数?,代表字符串的长度。
接下来一行?个小写字母,代表该字符串。
【输出格式】
一行一个整数代表答案。
【样例输入】
10
aabbaaabab
【样例输出】
3
【数据范围与规定】
3。
60%的数据,1 ≤ ? ≤ 1000。
对于100%的数据,1 ≤ ? ≤ 10 6 .
1 #include <algorithm> 2 #include <cstdio> 3 4 #define max(a,b) (a>b?a:b) 5 #define min(a,b) (a<b?a:b) 6 inline void read(int &x) 7 { 8 x=0; register char ch=getchar(); 9 for(; ch>'9'||ch<'0'; ) ch=getchar(); 10 for(; ch>='0'&&ch<='9'; ch=getchar()) x=x*10+ch-'0'; 11 } 12 const int N(1e6+5); 13 int cnt[28][N]; 14 char s[N]; 15 int n,ans; 16 17 int Presist() 18 { 19 freopen("a.in","r",stdin); 20 freopen("a.out","w",stdout); 21 read(n); 22 scanf("%s",s+1); 23 for(int i=0; i<27; ++i) 24 for(int j=1; j<=n; ++j) 25 { 26 if((s[j]-'a')!=i) cnt[i][j]+=cnt[i][j-1]; 27 else cnt[i][j]+=cnt[i][j-1]+1; 28 } 29 int maxx,minn; 30 for(int i=0; i<=n; ++i) 31 { 32 for(int j=i+1; j<=n; ++j) 33 { 34 maxx=0,minn=0x3f3f3f3f; 35 for(int k=0; k<27; ++k) 36 { 37 if(cnt[k][j]-cnt[k][i]) 38 minn=min(minn,cnt[k][j]-cnt[k][i]); 39 maxx=max(maxx,cnt[k][j]-cnt[k][i]); 40 } 41 ans=max(ans,maxx-minn); 42 } 43 } 44 printf("%d\n",ans); 45 return 0; 46 } 47 48 int Aptal=Presist(); 49 int main(int argc,char*argv[]){;}
1 /* 2 枚举右端点,前缀和优化。对于当前点x,答案为 3 sum[x][r]-sum[x][l-1]-(sum[z][r]-sum[z][l-1]) 4 整理为 sum[x][r]-sum[z][r]-(sum[x][l-1]-sum[z][l-1]) 5 我们已知x和sum[x][r],对于z我们枚举, 6 对于sum[x][l-1]-sum[z][l-1]我们需要一个最小的 7 用minv[x][y]表示sum[x]-sum[y]的最小值。 8 */ 9 #include <cstdio> 10 11 #define max(a,b) (a>b?a:b) 12 13 const int N(1e6+5); 14 const int M(26); 15 16 char s[N]; 17 int n,pos[M][M],last[M]; 18 int ans,sum[M],minn[M][M]; 19 20 int Presist() 21 { 22 scanf("%d%s",&n,s); 23 for(int now,i=0; i<n; ++i) 24 { 25 now=s[i]-'a'; 26 last[now]=i; 27 sum[now]++; 28 for(int k=0; k<M; ++k) 29 if(k!=now&&sum[k]) 30 ans=max(ans, max(sum[now]-sum[k]-minn[now][k]-(last[k]==pos[now][k]), 31 sum[k]-sum[now]-minn[k][now]-(last[k]==pos[k][now])) ); 32 for(int k=0; k<M; ++k) 33 { 34 if(sum[k]-sum[now]<minn[k][now]) minn[k][now]=sum[k]-sum[now],pos[k][now]=i; 35 if(sum[now]-sum[k]<minn[now][k]) minn[now][k]=sum[now]-sum[k],pos[now][k]=i; 36 } 37 } 38 printf("%d\n",ans); 39 return 0; 40 } 41 42 int Aptal=Presist(); 43 int main(int argc,char**argv){;}
P97 zhxb
第 3 页 共 5 页
T2 b
【问题描述】
你是能看到第二题的 friends 呢。
——laekov
Hja 和 Yjq 在玩捉迷藏。Yjq 躲了起来,Hja 要找他。在他们玩游戏的房间
里,只有一堵不透明的墙和一个双面的镜子。Hja 和 Yjq 可以看作平面上坐标分
别为(? ? ,? ? )和(? ? ,? ? )的点。墙是一条连接(? ? 1 ,? ? 1 )和(? ? 2 ,? ? 2 )的线段,镜子是
一条连接(? ? 1 ,? ? 1 )和(? ? 2 ,? ? 2 )的线段。
如果视线和障碍物有公共点,那么我们认为视线会被阻挡,无法看见。如果
视线和镜子有公共点,那么我们认为发生了反射。反射的过程遵循物理规律——
入射角等于反射角,且反射光线与入射光线在镜子同侧。也就是说,想要看见对
方,Hja 和 Yjq 必须在镜子的同一侧,包括镜子所在直线上(参见样例 1) 。如果
视线与镜子重合, 那么不会发生反射, 并且镜子不被当作障碍物 (参见样例 4) 。
Hja 很想知道他站在原地能否看见 Yjq,帮助他解决这个问题。
【输入格式】
第一行两个数? ? ,? ? ,表示 Hja 的坐标。
第二行两个数? ? ,? ? 表示 Yjq 的坐标。
第三行四个数? ? 1 ,? ? 1 ,? ? 2 ,? ? 2 ,分别表示墙的两个端点的坐标。
第四行四个数? ? 1 ,? ? 1 ,? ? 2 ,? ? 2 ,分别表示镜子的两个端点的坐标。
【输出格式】
如果 Hja 站在原地能看到 Yjq,则输出"YES",否则输出"NO"。
【样例输入 1】
-1 3
1 3
0 2 0 4
0 0 0 1
【样例输出 1】
NO
P97 zhxb
第 4 页 共 5 页
【样例输入 2】
0 0
1 1
0 1 1 0
-100 -100 -101 -101
【样例输出 2】
NO
【样例输入 3】
0 0
1 1
0 1 1 0
-1 1 1 3
【样例输出 3】
YES
【样例输入 4】
0 0
10 0
100 100 101 101
1 0 3 0
【样例输出 4】
YES
【数据规模与约定】
对于100%的数据,所有坐标均为绝对值不超过10 4 的整数。输入的线段不会
退化成点,且两条线段没有交点。Hja 和 Yjq 的位置不同,且不在任何一条线段
上。
1 #include<cstdio> 2 #include<cstdlib> 3 #include<cstring> 4 #include<cmath> 5 #include<algorithm> 6 using namespace std; 7 const double eps=1e-8; 8 int sgn(double a) 9 { 10 if (fabs(a)<eps) return 0; 11 else 12 { 13 if (a>0.0) return 1; 14 else return -1; 15 } 16 } 17 struct point 18 { 19 double x,y; 20 point(){} 21 point(double a,double b) 22 { 23 x=a;y=b; 24 } 25 void init() 26 { 27 scanf("%lf%lf",&x,&y); 28 } 29 point operator+(const point &a)const 30 { 31 point ans; 32 ans.x=x+a.x; 33 ans.y=y+a.y; 34 return ans; 35 } 36 point operator-(const point &a)const 37 { 38 point ans; 39 ans.x=x-a.x; 40 ans.y=y-a.y; 41 return ans; 42 } 43 point operator*(const double &a)const 44 { 45 point ans; 46 ans.x=x*a; 47 ans.y=y*a; 48 return ans; 49 } 50 void print() 51 { 52 printf("%lf %lf\n",x,y); 53 } 54 }v,p,w1,w2,m1,m2; 55 double cross(point a,point b) 56 { 57 return a.x*b.y-a.y*b.x; 58 } 59 double dot(point a,point b) 60 { 61 return a.x*b.x+a.y*b.y; 62 } 63 bool cross(point p1,point p2,point p3,point p4) 64 { 65 if (sgn(cross(p2-p1,p3-p1))*sgn(cross(p2-p1,p4-p1))==1) return false; 66 if (sgn(cross(p4-p3,p1-p3))*sgn(cross(p4-p3,p2-p3))==1) return false; 67 if (sgn(max(p1.x,p2.x)-min(p3.x,p4.x))==-1) return false; 68 if (sgn(max(p1.y,p2.y)-min(p3.y,p4.y))==-1) return false; 69 if (sgn(max(p3.x,p4.x)-min(p1.x,p2.x))==-1) return false; 70 if (sgn(max(p3.y,p4.y)-min(p1.y,p2.y))==-1) return false; 71 return true; 72 } 73 point getcross(point p1,point p2,point p3,point p4) 74 { 75 double a=p2.y-p1.y; 76 double b=p1.x-p2.x; 77 double c=-p1.x*p2.y+p1.y*p2.x; 78 double d=p4.y-p3.y; 79 double e=p3.x-p4.x; 80 double f=-p3.x*p4.y+p3.y*p4.x; 81 double x=(b*f-c*e)/(a*e-b*d); 82 double y=(a*f-c*d)/(b*d-a*e); 83 return point(x,y); 84 } 85 point calcfoot(point p1,point p2,point p3) 86 { 87 double ratio=dot(p1-p2,p3-p2)/dot(p3-p2,p3-p2); 88 return p2+(p3-p2)*ratio; 89 } 90 bool check() 91 { 92 if (!cross(v,p,w1,w2)) 93 { 94 if (!cross(v,p,m1,m2)) return true; 95 if (sgn(cross(m1-v,m2-v))==0 && sgn(cross(m1-p,m2-p)==0)) return true; 96 } 97 if (sgn(cross(m2-m1,v-m1))*sgn(cross(m2-m1,p-m1))==1) 98 { 99 point foot=calcfoot(p,m1,m2); 100 foot=foot*2.0-p; 101 if (cross(v,foot,m1,m2)) 102 { 103 foot=getcross(v,foot,m1,m2); 104 if (!cross(v,foot,w1,w2) && !cross(foot,p,w1,w2)) return true; 105 } 106 } 107 return false; 108 } 109 int main() 110 { 111 freopen("b.in","r",stdin); 112 freopen("b.out","w",stdout); 113 v.init(); 114 p.init(); 115 w1.init(); 116 w2.init(); 117 m1.init(); 118 m2.init(); 119 if (check()) printf("YES\n"); 120 else printf("NO\n"); 121 return 0; 122 }
P97 zhxc
第 5 页 共 5 页
T3 c
【问题描述】
你是能看到第三题的 friends 呢。
——aoao
众所周知,八数码问题是一个非常难的问题,但是 Yjq 非常有面子,他把这
道题简化了一番。 现在给了你一个3 × 3的方格图, 你的目标是通过不断移动使得
相邻颜色的块形成联通块。 你每次的移动方式是选择一列或者一行进行置换滑动
(这个解释起来比较麻烦,看下面的图就懂了) 。所谓置换滑动,就是所有格子
沿着给定的方向顺次移动, 最后一个格子会被置换到最前面的过程。 现在给定整
个方格图,以及每个格子是否能够移动,求使得相同颜色联通的最小步数。
【输入格式】
输入为3 × 3的方格图,每个位置由五个字符组成,前四个字符分别表示上下
左右四个部分的颜色, 第五个字符表示该格子是否能够移动, 其中0是能移动1是
不能移动。
【输出格式】
一行一个整数代表答案。
【样例输入】
GGGG0 GGGG0 GGGG0
OGOO0 GGGG0 OGOO0
OOOO0 OGGG1 OOOO0
【样例输出】
5
【样例解释】
【数据规模与约定】
对于100%的数据,所有颜色只可能是 RGBO 中的一种,且一定有解。
1 #include<cstdio> 2 #include<cstdlib> 3 #include<cstring> 4 #include<queue> 5 6 using namespace std; 7 8 #define get(a,b,c) ((a-1)*12+(b-1)*4+c) 9 10 int en,tmp[4][4],color[37],map[9][5],q[37],nowmap[4][4],newmap[4][4]; 11 12 bool num[9],use[90000000],right[37],row[4],col[4],col_find[5]; 13 14 char s[10]; 15 16 struct rec 17 { 18 int sta,step; 19 rec(){} 20 rec(int a,int b) 21 { 22 sta=a;step=b; 23 } 24 }; 25 26 queue<rec> que; 27 28 struct edge 29 { 30 int e; 31 edge *next; 32 }*v[37],ed[100]; 33 34 void add_edge(int s,int e) 35 { 36 en++; 37 ed[en].next=v[s];v[s]=ed+en;v[s]->e=e; 38 en++; 39 ed[en].next=v[e];v[e]=ed+en;v[e]->e=s; 40 } 41 42 bool check(int nows) 43 { 44 memset(num,false,sizeof(num)); 45 for (int a=3;a>=1;a--) 46 for (int b=3;b>=1;b--) 47 if (a!=3 || b!=3) 48 { 49 tmp[a][b]=nows%10; 50 num[nows%10]=true; 51 nows/=10; 52 } 53 for (int a=0;a<9;a++) 54 if (!num[a]) 55 { 56 tmp[3][3]=a; 57 break; 58 } 59 int cnt=0; 60 for (int a=1;a<=3;a++) 61 for (int b=1;b<=3;b++) 62 for (int c=1;c<=4;c++) 63 { 64 cnt++; 65 color[cnt]=map[tmp[a][b]][c]; 66 } 67 memset(right,false,sizeof(right)); 68 memset(col_find,false,sizeof(col_find)); 69 for (int a=1;a<=36;a++) 70 if (!right[a]) 71 { 72 if (col_find[color[a]]) return false; 73 col_find[color[a]]=true; 74 int front=1,tail=1; 75 q[1]=a; 76 right[a]=true; 77 for (;front<=tail;) 78 { 79 int now=q[front++]; 80 for (edge *e=v[now];e;e=e->next) 81 if (color[e->e]==color[now] && !right[e->e]) 82 { 83 right[e->e]=true; 84 q[++tail]=e->e; 85 } 86 } 87 } 88 return true; 89 } 90 91 int main() 92 { 93 freopen("c.in","r",stdin); 94 freopen("c.out","w",stdout); 95 96 for (int a=1;a<=3;a++) 97 for (int b=1;b<=3;b++) 98 { 99 add_edge(get(a,b,1),get(a,b,3)); 100 add_edge(get(a,b,1),get(a,b,4)); 101 add_edge(get(a,b,2),get(a,b,3)); 102 add_edge(get(a,b,2),get(a,b,4)); 103 if (a!=3) add_edge(get(a,b,2),get(a+1,b,1)); 104 if (b!=3) add_edge(get(a,b,4),get(a,b+1,3)); 105 } 106 int cnt=0; 107 for (int a=1;a<=3;a++) 108 for (int b=1;b<=3;b++) 109 { 110 scanf("%s",s+1); 111 for (int c=1;c<=4;c++) 112 if (s[c]=='R') map[cnt][c]=0; 113 else 114 { 115 if (s[c]=='G') map[cnt][c]=1; 116 else 117 { 118 if (s[c]=='B') map[cnt][c]=2; 119 else map[cnt][c]=3; 120 } 121 } 122 if (s[5]=='1') row[a]=col[b]=true; 123 cnt++; 124 } 125 int nows=1234567; 126 if (check(nows)) 127 { 128 printf("0\n"); 129 return 0; 130 } 131 que.push(rec(nows,0)); 132 use[nows]=true; 133 rec now; 134 while (que.size()) 135 { 136 now=que.front(); 137 que.pop(); 138 int step=now.step; 139 int nows=now.sta; 140 memset(num,false,sizeof(num)); 141 for (int a=3;a>=1;a--) 142 for (int b=3;b>=1;b--) 143 if (a!=3 || b!=3) 144 { 145 nowmap[a][b]=nows%10; 146 num[nows%10]=true; 147 nows/=10; 148 } 149 for (int a=0;a<9;a++) 150 if (!num[a]) 151 { 152 nowmap[3][3]=a; 153 break; 154 } 155 int news=0; 156 for (int a=1;a<=3;a++) 157 { 158 if (!row[a]) 159 { 160 for (int b=1;b<=3;b++) 161 for (int c=1;c<=3;c++) 162 newmap[b][c]=nowmap[b][c]; 163 int x=newmap[a][1]; 164 newmap[a][1]=newmap[a][2];newmap[a][2]=newmap[a][3];newmap[a][3]=x; 165 news=0; 166 for (int b=1;b<=3;b++) 167 for (int c=1;c<=3;c++) 168 if (b!=3 || c!=3) news=news*10+newmap[b][c]; 169 if (!use[news]) 170 { 171 use[news]=true; 172 if (check(news)) 173 { 174 printf("%d\n",step+1); 175 return 0; 176 } 177 que.push(rec(news,step+1)); 178 } 179 x=newmap[a][1]; 180 newmap[a][1]=newmap[a][2];newmap[a][2]=newmap[a][3];newmap[a][3]=x; 181 news=0; 182 for (int b=1;b<=3;b++) 183 for (int c=1;c<=3;c++) 184 if (b!=3 || c!=3) news=news*10+newmap[b][c]; 185 if (!use[news]) 186 { 187 use[news]=true; 188 if (check(news)) 189 { 190 printf("%d\n",step+1); 191 return 0; 192 } 193 que.push(rec(news,step+1)); 194 } 195 } 196 if (!col[a]) 197 { 198 for (int b=1;b<=3;b++) 199 for (int c=1;c<=3;c++) 200 newmap[b][c]=nowmap[b][c]; 201 int x=newmap[1][a]; 202 newmap[1][a]=newmap[2][a];newmap[2][a]=newmap[3][a];newmap[3][a]=x; 203 news=0; 204 for (int b=1;b<=3;b++) 205 for (int c=1;c<=3;c++) 206 if (b!=3 || c!=3) news=news*10+newmap[b][c]; 207 if (!use[news]) 208 { 209 use[news]=true; 210 if (check(news)) 211 { 212 printf("%d\n",step+1); 213 return 0; 214 } 215 que.push(rec(news,step+1)); 216 } 217 x=newmap[1][a]; 218 newmap[1][a]=newmap[2][a];newmap[2][a]=newmap[3][a];newmap[3][a]=x; 219 news=0; 220 for (int b=1;b<=3;b++) 221 for (int c=1;c<=3;c++) 222 if (b!=3 || c!=3) news=news*10+newmap[b][c]; 223 if (!use[news]) 224 { 225 use[news]=true; 226 if (check(news)) 227 { 228 printf("%d\n",step+1); 229 return 0; 230 } 231 que.push(rec(news,step+1)); 232 } 233 } 234 } 235 } 236 237 return 0; 238 }