码迷,mamicode.com
首页 > 其他好文 > 详细

2017.10.1北京清北综合强化班DAY1

时间:2017-10-01 19:54:53      阅读:181      评论:0      收藏:0      [点我收藏+]

标签:sum   none   ble   while   ons   tor   efi   mes   必须   

a
【问题描述】
你是能看到第一题的 friends呢。
                                                         —— hja
何大爷对字符串十分有研究,于是天出题虐杀 zhx。何大爷今天为 何大爷今天为 字符串定义了新的权值计算方法。一个由小写母组成,被定义为其中出现次数最多的字符减去少。(注 被定义为其中出现次数最多的字符减去少。(注 意,在讨论出现最少的字符时候该必须至一次)何大爷给你一个字符串,何大爷想知道这的所有子中权值最是多少?
【输入格式】
第一行 一个整数 ??,代表字符串的长度 。
接下来一行 ??个小写字母,代表该符串。
【输出格式】
一行个整数代表答案。
【样例输入】
10
aabbaaabab
【样例输出】
3

【数据范围与规定】
对于 30%的数据, 1≤??≤100。
对于 60%的数据, 1≤??≤1000。
对于 100%的数据, 1≤??≤106.

题目大意:求一个字符串子串的最多出现次数-最少出现次数的最大值。

题解:

30分做法O(n^3)枚举区间 扫最大最小值

60分做法O(26n^2)枚举区间 前缀和求最大最小值

技术分享
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
int n,maxx,minn,ans,sum[1020][26];
char s[1020];
int main(){
    scanf("%d",&n);scanf("%s",s+1);
    for(int i=1;i<=n;i++){
        for(int j=1;j<=26;j++)sum[i][j]=sum[i-1][j];
        int z=s[i]-a+1;
        sum[i][z]=sum[i-1][z]+1;
    }
    for(int i=1;i<=n;i++){
        for(int j=i;j<=n;j++){
            if(i==j){
                ans=max(ans,0);
                continue;
            }
            maxx=-1;minn=100000;
            for(int k=1;k<=26;k++){
                int z=sum[j][k]-sum[i-1][k];
                if(z)minn=min(minn,z);
                maxx=max(maxx,z);
            }
            ans=max(ans,maxx-minn);
        }
    }
    printf("%d\n",ans);
    return 0;
}
60分

 

枚举右端点,前缀和优化。对于当前点x,答案为

sum[x][r]-sum[x][l-1]-(sum[z][r]-sum[z][l-1])

整理为

sum[x][r]-sum[z][r]-(sum[x][l-1]-sum[z][l-1])

我们已知x和sum[x][r],对于z我们枚举,对于sum[x][l-1]-sum[z][l-1]我们需要一个最小的

用minv[x][y]表示sum[x]-sum[y]的最小值。

技术分享
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<vector>

using namespace std;

const int maxn=1000010;

int n,ans,p[26][26],minv[26][26],sum[26],last[26];

char s[maxn];

int main()
{
    freopen("a.in","r",stdin);
    freopen("a.out","w",stdout);

    scanf("%d",&n);
    scanf("%s",s+1);
    for (int a=1;a<=n;a++)
    {
        int c=s[a]-a;
        sum[c]++;
        last[c]=a;
        for (int b=0;b<26;b++)
            if (b!=a && sum[b]) ans=max(ans,max(sum[c]-sum[b]-minv[c][b]-(last[b]==p[c][b]),sum[b]-sum[c]-minv[b][c]-(last[b]==p[b][c])));
        for (int b=0;b<26;b++)
        {
            if (sum[c]-sum[b]<minv[c][b]) minv[c][b]=sum[c]-sum[b],p[c][b]=a;
            if (sum[b]-sum[c]<minv[b][c]) minv[b][c]=sum[b]-sum[c],p[b][c]=a;
        }
    }
    printf("%d\n",ans);

    return 0;
}
AC

 

 

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

【样例输入2】
0
1
0

【样例输出2】
NO
【样例输入3】
0
1
0
1 -1 3
【样例输出3】
YES
【样例输入4】

YES

【数据规模与约定】
对于 100%的数据, 所有坐标均为绝对值不超过 所有坐标均为绝对值不超过 104的整数。输入线段不会 的整数。输入线段不会 退化成点,且两条线段没有交。 退化成点,且两条线段没有交。 Hja和 Yjq的位置不同,且不在任何一条线段 的位置不同。

题解:计算几何 弃疗

代码:

技术分享
#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;
}
AC

 

 

【问题描述】
你是能看到第三题的 friends呢。
                                          —— aoao
众所周知 ,八数码 问题 是一个 非常 难的问题 ,但是 Yjq非常 有面子 ,他把这 道题 简化了 一番 。现在 给了 你一个 3×3的方格图 ,你的 目标 是通过 不断 移动 使得 相邻 颜色 的块形成联通 块。你每次 的移动 方式 是选择 一列 或者 一行 进行 置换 滑动 (这个 解释 起来 比较 麻烦 ,看下面 的图就懂了 )。所谓 置换 滑动 ,就是 所有 格子 沿着 给定 的方向 顺次 移动 ,最后 一个 格子 会被 置换到 最前面 的过程 。现在 给定 整 个方格图 ,以及 每个 格子 是否 能够 移动 ,求使得 相同 颜色 联通 的最小步数 。
【输入格式】
输入 为3×3的方格图 ,每个 位置 由五个字符 组成 ,前四个字符 分别 表示 上下 左右 四个 部分 的颜色 ,第五个 字符 表示 该格子 是否 能够 移动 ,其中 0是能移动 1是 不能移动 。
【输出格式】
一行个整数代表答案。

 

 

技术分享

题解:爆搜

技术分享
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<queue>

using namespace std;

#define get(a,b,c) ((a-1)*12+(b-1)*4+c)

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

 

2017.10.1北京清北综合强化班DAY1

标签:sum   none   ble   while   ons   tor   efi   mes   必须   

原文地址:http://www.cnblogs.com/zzyh/p/7617632.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!