2017.10.6 P97-zhx

来源:互联网 发布:avena 36一盒粉末淘宝 编辑:程序博客网 时间:2024/06/10 09:27

此图镇楼

(我向苍天续一秒)

T1 a

【问题描述】

你是能看到第一题的friends 呢。
——hja
何大爷对字符串十分有研究,于是天天出字符串题虐杀zhx。何大爷今天为
字符串定义了新的权值计算方法。一个字符串由小写字母组成,字符串的权值
被定义为其中出现次数最多的字符的次数减去出现次数最少的字符的次数。(注
意,在讨论出现最少的字符的时候,该字符必须至少出现一次)现在何大爷给
你一个字符串,何大爷想知道这个字符串的所有子串中权值最大的权值是多
少?

【输入格式】

第一行一个整数n,代表字符串的长度。
接下来一行n个小写字母,代表该字符串。

【输出格式】

一行一个整数代表答案。

【样例输入】

10
aabbaaabab

【样例输出】

3

【数据范围与规定】

对于30%的数据,1 ≤ n ≤ 100。
对于60%的数据,1 ≤ n ≤ 1000。
对于100%的数据,1 ≤ n ≤ 10^6。

题解

(闹鬼了,这几天集训头题都这么难。。。)

这题嘛,定睛一看,
30分:大暴力,枚举l,r,排序
60分:排个球啊,前缀和弄一下就完了。。。,O(26*n^2)
100分:

——(sum[a][r]-sum[a][l-1])-(sum[b][r]-sum[b][l-1])

==>(sum[a][r]-sum[b][r])-(sum[a][l-1]-sum[b][l-1])

我们枚举r,a是右端点的字符,b是我们在[l,r]中找的字符,搞下每个字符的前缀和,
用MIN[x][y]表示sum[x]-sum[y]的最小值,每次处理一下,于是,世界和谐

代码

#include <cstdio>#include <iostream>#include <string>#include <algorithm>using namespace std;#define MAX_N 100000+10#define MAX_S 30typedef long long ll;ll read() {    ll x=0,f=1;char ch=getchar();    while(ch<'0'||ch>'9') {if(ch=='-')f=-1;ch=getchar();}    while(ch>='0'&&ch<='9') {x=x*10+ch-'0';ch=getchar();}    return x*f;}int n;string s;int pos[MAX_S];int a[MAX_S][MAX_S];int sum[MAX_S];int MIN[MAX_S][MAX_S];int ans;int main() {    //freopen("a.in","r",stdin);    //freopen("a.out","w",stdout);    n=read();    cin>>s;    for(int i=0;i<n;i++) {        int c=s[i]-'a';        sum[c]++,pos[c]=i;        for(int j=0;j<26;j++)            if(c!=j&&sum[j]!=0) {//小坑                int res;                res=max(sum[c]-sum[j]-MIN[c][j],sum[j]-sum[c]-MIN[j][c]);                if(pos[j]==a[c][j])                    res--;                ans=max(ans,res);            }        for(int j=0;j<26;j++) {            if(sum[c]-sum[j]<MIN[c][j]) {                MIN[c][j]=sum[c]-sum[j];                a[c][j]=i;            }            if(sum[j]-sum[c]<MIN[j][c]) {                MIN[j][c]=sum[j]-sum[c];                a[j][c]=i;            }        }    }    cout<<ans<<endl;    return 0;}

T2 b

【问题描述】

你是能看到第二题的 friends呢。
—— laekov
Hja和 Yjq在玩捉迷藏。 Yjq躲了起来, Hja要找他。在们玩游戏的房间里,只有一堵不透明的墙和一个双面镜子。Hja和 Yjq可以看作平面上坐标分别为 (Xv,Yv)和(Xp,Yp)的点。墙是一条连接 (Xw1,Yw1)和(Xw2,Yw2)的线段,镜子是一条连接 (Xm1,Ym1)和(Xm2,Ym2)的线段。
如果视线和障碍物有公共点,那么我们认为会被阻挡,无法看见。视线和镜子有公共点,那么我们认为发生了反射。反射的过程遵循物理规律—— 入射角等于反射角,且反射光线与入射光线在镜子同侧。也就是说想要看见对 方,Hja和 Yjq必须在镜子的同一侧,包括所直线上(参见样例 必须在镜子的同一侧,包括所直线上(参见样例 必须在镜子的同一侧,包括镜子所在直线上(参见样例 1)。如果视线与镜子重合,那么不会发生反射,并且镜子不被当作障碍物(参见样例 4)
Hja很想知道他站在原地能否看见 Yjq,帮助他解决这个问题。

【输入格式】

第一行两个数 Xv,Yv,表示 Hja的坐标。
第二行两个数 Xp,Yp表示 Yjq的坐标。
第三行四个数 Xw1,Yw1,Xw2,Yw2,分别表示墙的两个端点坐标。
第四行个数Xm1,Ym1,Xm2,Ym2,分别表示镜子的两个端点坐标。

【输出格式】

如果 Hja站在原地能看到 Yjq,则输出 “YES”,否则输出 “NO”。

【样例输入1】

-1 3
1 3
0 2 0 4
0 0 0 1

【样例输出1】

NO

【样例输入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%的数据, 所有坐标均为绝对值不超过 所有坐标均为绝对值不超过 104的整数。输入线段不会10^4的整数。输入的线段不会退化成点,且两条线段没有交点。Hja和 Yjq的位置不同,且在任何一条线段的位置不同,且在任何一条线段上

题解

这个,这个。。。长者送分啊。。。随机居然有61.。。。计算几何呀,画画图就知道了。。。
你需要知道:叉乘,对称性,等等。。。

代码(标程)

#include<cstdio>#include<cstdlib>#include<cstring>#include<cmath>#include<algorithm>using namespace std;const double eps=1e-8;int sgn(double a) {    if (fabs(a)<eps) return 0;    else {        if (a>0.0) return 1;        else return -1;    }}struct point {    double x,y;    point() {}    point(double a,double b) {        x=a;        y=b;    }    void init() {        scanf("%lf%lf",&x,&y);    }    point operator+(const point &a)const {        point ans;        ans.x=x+a.x;        ans.y=y+a.y;        return ans;    }    point operator-(const point &a)const {        point ans;        ans.x=x-a.x;        ans.y=y-a.y;        return ans;    }    point operator*(const double &a)const {        point ans;        ans.x=x*a;        ans.y=y*a;        return ans;    }    void print() {        printf("%lf %lf\n",x,y);    }} v,p,w1,w2,m1,m2;double cross(point a,point b) {    return a.x*b.y-a.y*b.x;}double dot(point a,point b) {    return a.x*b.x+a.y*b.y;}bool cross(point p1,point p2,point p3,point p4) {    if (sgn(cross(p2-p1,p3-p1))*sgn(cross(p2-p1,p4-p1))==1) return false;    if (sgn(cross(p4-p3,p1-p3))*sgn(cross(p4-p3,p2-p3))==1) return false;    if (sgn(max(p1.x,p2.x)-min(p3.x,p4.x))==-1) return false;    if (sgn(max(p1.y,p2.y)-min(p3.y,p4.y))==-1) return false;    if (sgn(max(p3.x,p4.x)-min(p1.x,p2.x))==-1) return false;    if (sgn(max(p3.y,p4.y)-min(p1.y,p2.y))==-1) return false;    return true;}point getcross(point p1,point p2,point p3,point p4) {    double a=p2.y-p1.y;    double b=p1.x-p2.x;    double c=-p1.x*p2.y+p1.y*p2.x;    double d=p4.y-p3.y;    double e=p3.x-p4.x;    double f=-p3.x*p4.y+p3.y*p4.x;    double x=(b*f-c*e)/(a*e-b*d);    double y=(a*f-c*d)/(b*d-a*e);    return point(x,y);}point calcfoot(point p1,point p2,point p3) {    double ratio=dot(p1-p2,p3-p2)/dot(p3-p2,p3-p2);    return p2+(p3-p2)*ratio;}bool check() {    if (!cross(v,p,w1,w2)) {        if (!cross(v,p,m1,m2)) return true;        if (sgn(cross(m1-v,m2-v))==0 && sgn(cross(m1-p,m2-p)==0)) return true;    }    if (sgn(cross(m2-m1,v-m1))*sgn(cross(m2-m1,p-m1))==1) {        point foot=calcfoot(p,m1,m2);        foot=foot*2.0-p;        if (cross(v,foot,m1,m2)) {            foot=getcross(v,foot,m1,m2);            if (!cross(v,foot,w1,w2) && !cross(foot,p,w1,w2)) return true;        }    }    return false;}int main() {    freopen("b.in","r",stdin);    freopen("b.out","w",stdout);    v.init();    p.init();    w1.init();    w2.init();    m1.init();    m2.init();    if (check()) printf("YES\n");    else printf("NO\n");    return 0;}

T3 c

【问题描述】

你是能看到第三题的 friends呢。
—— aoao
众所周知 ,八数码 问题 是一个 非常 难的问题 ,但是 Yjq非常 有面子 ,他把这 道题 简化了 一番 。现在 给了 你一个 3×3的方格图 ,你的 目标 是通过 不断 移动 使得 相邻 颜色 的块形成联通 块。你每次 的移动 方式 是选择 一列 或者 一行 进行 置换 滑动 (这个 解释 起来 比较 麻烦 ,看下面 的图就懂了 )。所谓 置换 滑动 ,就是 所有 格子 沿着 给定 的方向 顺次 移动 ,最后 一个 格子 会被 置换到 最前面 的过程 。现在 给定 整 个方格图 ,以及 每个 格子 是否 能够 移动 ,求使得 相同 颜色 联通 的最小步数 。

【输入格式】

输入 为3×3的方格图 ,每个 位置 由五个字符 组成 ,前四个字符 分别 表示 上下 左右 四个 部分 的颜色 ,第五个 字符 表示 该格子 是否 能够 移动 ,其中 0是能移动 1是 不能移动 。

【输出格式】

一行个整数代表答案。

【样例输入】

GGGG0
OGOO0
GGGG0 OOOO0
OGGG1

【样例输出】

5

【样例解释】

样例解释

【数据规模与约定】

对于 100%的数据 ,所有颜色 只可能是 RGBO中的一种 ,且一定 有解 。

题解

就是爆 搜 啦
长者说:爆搜我不会讲。。。。。。。。。。。。

代码(标程)

#include<cstdio>#include<cstdlib>#include<cstring>#include<queue>#define get(a,b,c) ((a-1)*12+(b-1)*4+c)using namespace std;int en,tmp[4][4],color[37],map[9][5],q[37],nowmap[4][4],newmap[4][4];bool num[9],use[90000000],right[37],row[4],col[4],col_find[5];char s[10];struct rec {    int sta,step;    rec() {}    rec(int a,int b) {        sta=a;        step=b;    }};queue<rec> que;struct edge {    int e;    edge *next;}*v[37],ed[100];void add_edge(int s,int e) {    en++;    ed[en].next=v[s];    v[s]=ed+en;    v[s]->e=e;    en++;    ed[en].next=v[e];    v[e]=ed+en;    v[e]->e=s;}bool check(int nows) {    memset(num,false,sizeof(num));    for(int a=3; a>=1; a--)        for(int b=3; b>=1; b--)            if(a!=3 || b!=3) {                tmp[a][b]=nows%10;                num[nows%10]=true;                nows/=10;            }    for(int a=0; a<9; a++)        if(!num[a]) {            tmp[3][3]=a;            break;        }    int cnt=0;    for(int a=1; a<=3; a++)        for(int b=1; b<=3; b++)            for(int c=1; c<=4; c++) {                cnt++;                color[cnt]=map[tmp[a][b]][c];            }    memset(right,false,sizeof(right));    memset(col_find,false,sizeof(col_find));    for(int a=1; a<=36; a++)        if(!right[a]) {            if(col_find[color[a]]) return false;            col_find[color[a]]=true;            int front=1,tail=1;            q[1]=a;            right[a]=true;            for( ; front<=tail; ) {                int now=q[front++];                for(edge *e=v[now]; e; e=e->next)                    if(color[e->e]==color[now] && !right[e->e]) {                        right[e->e]=true;                        q[++tail]=e->e;                    }            }        }    return true;}int main() {    freopen("c.in","r",stdin);    freopen("c.out","w",stdout);    for(int a=1; a<=3; a++)        for(int b=1; b<=3; b++) {            add_edge(get(a,b,1),get(a,b,3));            add_edge(get(a,b,1),get(a,b,4));            add_edge(get(a,b,2),get(a,b,3));            add_edge(get(a,b,2),get(a,b,4));            if (a!=3) add_edge(get(a,b,2),get(a+1,b,1));            if (b!=3) add_edge(get(a,b,4),get(a,b+1,3));        }    int cnt=0;    for(int a=1; a<=3; a++)        for(int b=1; b<=3; b++) {            scanf("%s",s+1);            for(int c=1; c<=4; c++)                if(s[c]=='R') map[cnt][c]=0;                else {                    if(s[c]=='G') map[cnt][c]=1;                    else {                        if(s[c]=='B') map[cnt][c]=2;                        else map[cnt][c]=3;                    }                }            if(s[5]=='1') row[a]=col[b]=true;            cnt++;        }    int nows=1234567;    if (check(nows)) {        printf("0\n");        return 0;    }    que.push(rec(nows,0));    use[nows]=true;    rec now;    while (que.size()) {        now=que.front();        que.pop();        int step=now.step;        int nows=now.sta;        memset(num,false,sizeof(num));        for(int a=3; a>=1; a--)            for(int b=3; b>=1; b--)                if(a!=3 || b!=3) {                    nowmap[a][b]=nows%10;                    num[nows%10]=true;                    nows/=10;                }        for(int a=0; a<9; a++)            if(!num[a]) {                nowmap[3][3]=a;                break;            }        int news=0;        for(int a=1; a<=3; a++) {            if(!row[a]) {                for(int b=1; b<=3; b++)                    for(int c=1; c<=3; c++)                        newmap[b][c]=nowmap[b][c];                int x=newmap[a][1];                newmap[a][1]=newmap[a][2];                newmap[a][2]=newmap[a][3];                newmap[a][3]=x;                news=0;                for (int b=1; b<=3; b++)                    for (int c=1; c<=3; c++)                        if (b!=3 || c!=3) news=news*10+newmap[b][c];                if (!use[news]) {                    use[news]=true;                    if (check(news)) {                        printf("%d\n",step+1);                        return 0;                    }                    que.push(rec(news,step+1));                }                x=newmap[a][1];                newmap[a][1]=newmap[a][2];                newmap[a][2]=newmap[a][3];                newmap[a][3]=x;                news=0;                for (int b=1; b<=3; b++)                    for (int c=1; c<=3; c++)                        if (b!=3 || c!=3) news=news*10+newmap[b][c];                if (!use[news]) {                    use[news]=true;                    if (check(news)) {                        printf("%d\n",step+1);                        return 0;                    }                    que.push(rec(news,step+1));                }            }            if(!col[a]) {                for(int b=1; b<=3; b++)                    for(int c=1; c<=3; c++)                        newmap[b][c]=nowmap[b][c];                int x=newmap[1][a];                newmap[1][a]=newmap[2][a];                newmap[2][a]=newmap[3][a];                newmap[3][a]=x;                news=0;                for(int b=1; b<=3; b++)                    for(int c=1; c<=3; c++)                        if(b!=3 || c!=3) news=news*10+newmap[b][c];                if(!use[news]) {                    use[news]=true;                    if(check(news)) {                        printf("%d\n",step+1);                        return 0;                    }                    que.push(rec(news,step+1));                }                x=newmap[1][a];                newmap[1][a]=newmap[2][a];                newmap[2][a]=newmap[3][a];                newmap[3][a]=x;                news=0;                for(int b=1; b<=3; b++)                    for(int c=1; c<=3; c++)                        if(b!=3 || c!=3) news=news*10+newmap[b][c];                if(!use[news]) {                    use[news]=true;                    if(check(news)) {                        printf("%d\n",step+1);                        return 0;                    }                    que.push(rec(news,step+1));                }            }        }    }    return 0;}

over.

原创粉丝点击