1. 程式人生 > >2017.10.1北京清北綜合強化班DAY1

2017.10.1北京清北綜合強化班DAY1

last 線段 display cross push 最大 輸出格式 最大值 置換

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