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[]){;}
60分暴力
 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){;}
AC

 

 


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 }
AC

 

posted @ 2017-10-09 20:33  Aptal丶  阅读(255)  评论(0编辑  收藏  举报