国庆七天乐 Day3

今天做的是山东第一届省赛,题目比昨天的容易,但是还是出了五道题,难道难题都只能叫大叔来做?

A: Phone Number

给出N个字符串,判断是否存在一个字符串是另一个字符串的前缀,之前做过一道类似的题,字典树判断前缀确实很方便。

#include<stdio.h>

#include<string.h>

#include<stdlib.h>



typedef struct

{

    int next[10];

    int alr, end;

}Trie;



Trie t[110000];

int tp, n;



int insert(char *x, int site)

{

    if(t[site].end)

        return 1;

    if(*x)

    {

        t[site].alr = 1;

        if(!t[site].next[*x - '0'])

            t[site].next[*x - '0'] = tp ++;

        insert(x + 1, t[site].next[*x - '0']);

    }

    else

    {

        t[site].end = 1;

        return t[site].alr;

    }

}



int main()

{

    int T, flag;

    char s[11];

    while( scanf("%d", &n), n )

    {

        tp = 1;

        flag = 0;

        while(n --)

        {

            scanf("%s", s);

            if(!flag && insert(s, 0))

                flag = 1;

        }

        if(flag)

            printf("NO\n");

        else

            printf("YES\n");

        memset(t, 0, sizeof(Trie) * (tp + 1));

    }

    return 0;

}

B: Balloons

这也是一道水题,简单的搜索,分别按照4个方向和八个方向找联通块的数目,然后输出这两种方式得到的结果,隽遒学弟敲的也很快,

也按照题目要求在每个样例之后输出了换行,结果PC^2返回了WA,我们把代码打印出来了,我帮他看了半天也没发现哪有错。后面

老大说试着样例之间输出换行就过了。

# include <cstdio>

# include <cstring>

int n;



bool m[103][103];

bool f[103][103];



const int go[4][2] = {0,1, 1,0, 0,-1, -1,0}; //注意判断是否越界



const int ju[8][2] = {0,1, 1,0, 0,-1, -1,0, -1,1, 1,1, 1,-1, -1,-1};



void f1(int x, int y)

{

    int xx, yy, i;

    f[x][y] = 1;

    for ( i = 0; i < 4; ++i )

    {

        xx = x + go[i][0];

        yy = y + go[i][1];

        if ( xx < 1 || xx > n || yy < 1 || yy > n || !m[xx][yy] || f[xx][yy] ) continue;

        f1(xx, yy);

    }

}



void f2(int x, int y)

{

    int xx, yy, i;

    f[x][y] = 1;

    for ( i = 0; i < 8; ++i )

    {

        xx = x + ju[i][0];

        yy = y + ju[i][1];

        if ( xx < 1 || xx > n || yy < 1 || yy > n || !m[xx][yy] || f[xx][yy] ) continue;

        f2(xx, yy);

    }

}



int t = 0;

int main()

{

    int i, j;

    char s[107];

    while ( scanf("%d", &n) != EOF )

    {

        ++t;



        if ( n == 0 ) break;

        for ( i = 1; i <= n; ++i )

        {

            scanf("%s", s+1);

            for ( j = 1; j <= n; ++j )

                if ( s[j] == '0' ) m[i][j] = 0;

                else m[i][j] = 1;

        }

        int ans1 = 0, ans2 = 0;

        memset(f, 0, sizeof(f));

        for ( i = 1; i <= n; ++i )

            for ( j = 1; j <= n; ++j )

                if ( m[i][j] && ! f[i][j] )

                {

                    ++ans1;

                    f1(i, j);

                }

        memset(f, 0, sizeof(f));

        for ( i = 1; i <= n; ++i )

            for ( j = 1; j <= n; ++j )

                if ( m[i][j] && ! f[i][j] )

                {

                    ++ans2;

                    f2(i, j);

                }

        if ( t > 1 ) printf("\n");

        printf("Case %d: %d %d\n", t, ans1, ans2);

    }

    return 0;

}

C: Clockwise

看了题解是计算几何 + DP,不会,先放着。

D: Shopping

最水的一道题,结果又给我碰上了,输出给定序列最大值 - 最小值的结果的两倍。当时为了敲起来简单,还排序了...

#include <stdio.h>

#include <string.h>

#include <stdlib.h>

#include <algorithm>

using namespace std;

const int MAXN = 100010;

int a[MAXN];



int main()

{

    int n;

    while(scanf("%d", &n), n)

    {

        for(int i = 0; i < n; i ++)

        {

            scanf("%d", &a[i]);

        }

        sort(a, a + n);

        printf("%d\n", (a[n - 1] - a[0]) * 2);

    }

    return 0;

}

E: Emergency

这题是我敲的,之前做过几乎一模一样的题。给出一个图,N个点,M条有向边,Q次操作,M和Q都是10万,N是300,现在假设所有的点都被破坏了,有两

种操作,0 x,修复x结点,意味着我们可以从一个点到另一个点经过x结点。如果x结点已经被修复,则输出一句话。1 x y,输出从x到y的经过修复好的点

的最短路长度,如果x或者y依然是破坏状态也是输出一句话,否则则看最短路是否存在,存在就输出值。一个变化的floyd就可以搞定,每次修复一个点就把

这个点当成k,做k为中间点,任意两点间的最短路。

#include <stdio.h>

#include <string.h>

#include <string.h>



const int MAXN = 350;

const int INF = 0x3f3f3f3f;

int d[MAXN][MAXN];

bool rec[MAXN];

int N, M, Q;



void ReadGraph()

{

    int x, y, z;

    for(int i = 0; i < N; i ++)

        for(int j = 0; j < N; j ++)

        {

            if(i == j) d[i][j] = 0;

            else d[i][j] = INF;

        }

    memset(rec, false, sizeof rec);

    while(M --)

    {

        scanf("%d%d%d", &x, &y, &z);

        if(d[x][y] > z)

            d[x][y] = z;

    }

}



void query()

{

    int op, x, y;

    while(Q --)

    {

        scanf("%d", &op);

        if(0 == op)

        {

            scanf("%d", &x);

            if(rec[x])

                printf("City %d is already recaptured.\n", x);

            if(!rec[x])

            {

                rec[x] = true;

                for(int i = 0; i < N; i ++)

                    for(int j = 0; j < N; j ++)

                    {

                        if(d[i][j] > d[i][x] + d[x][j])

                            d[i][j] = d[i][x] + d[x][j];

                    }

            }

        }

        if(1 == op)

        {

            scanf("%d%d", &x, &y);

            if(rec[x] && rec[y])

            {

                if(d[x][y] < INF)

                    printf("%d\n", d[x][y]);

                else

                    printf("No such path.\n");

            }

            else

            {

                printf("City %d or %d is not available.\n", x, y);

            }

        }

    }

}



int main()

{

    freopen("emergency.in", "r", stdin);

    freopen("Edata.txt", "w", stdout);

    int t = 1;

    while(scanf("%d%d%d", &N, &M, &Q), N + M + Q)

    {

        ReadGraph();

        if(t > 1) printf("\n");

        printf("Case %d:\n", t ++);

        query();

        //printf("\n");

    }

    return 0;

}

F:Fairy tale

模拟题,比赛时隽遒学弟在敲,当时没出,结束后交题过了。

# include <cstdio>

# include <cstring>

# define rep(x) for ( x = 1; x <= n; ++x )

const int go[4][2] = {0,1, 0,-1, 1,0, -1,0}; //E,W,S,N

const int pgo[4][2] = {0,1, 0,-1, -1,0, 1,0}; //E,W,N,S prefer!



const int inf = 2147483647;

int n;

int m[35][35];

bool f[31][31][31][31][4];

bool circle;



int x, y, tx, ty, time;



int abs(int x) { return x > 0 ? x: -x; }

int sqr(int x) { return x * x; }



bool inside(int x, int y)

{ return (x > 0 && x <= n && y > 0 && y <= n); }



bool better(int x, int y, int xx,int yy)

{ return sqr(x-tx)+sqr(y-ty) < sqr(xx-tx)+sqr(yy-ty); }



void Init()

{

    int i,j,k,l,p;

    char s[35];

    rep(i) rep(j) rep(k) rep(l)

        for (p = 0; p < 4; ++p )

            f[i][j][k][l][p] = false;

    rep(i)

    {

        scanf("%s", s+1);

        rep(j)

            if ( s[j] == 'E' ) m[i][j] = 0;

            else if ( s[j] == 'W' ) m[i][j] = 1;

            else if ( s[j] == 'S' ) m[i][j] = 2;

            else if ( s[j] == 'N' ) m[i][j] = 3;

    }

    x = y = 1;

    tx = ty = n;

    time = 0;

    circle = false;

}



int cnt = 0;

int sec[103][5];

bool check()

{

    int i;

    for ( i = 1; i < time; ++i )

        if ( sec[i][0] == x && sec[i][1] == y && sec[i][2] == tx && sec[i][3] == ty && sec[i][4] == (time&3) )

        {

            circle = true;

            return true;

        }

    sec[i][0] = x,sec[i][1] = y,sec[i][2]= tx, sec[i][3] = ty, sec[i][4]= (time&3);

    return false;

}



bool step()

{

    int f1 = (m[x][y]+time)&3, f2 = (m[tx][ty]+time)&3;

    if ( x == tx && y == ty ) return true;

    if ( check() ) return false;

    int xx = x + go[f1][0];

    int yy = y + go[f1][1];

    if ( inside(xx,yy) ) x = xx, y = yy; //自动走

    xx = x, yy = y;

    for ( int i = 0; i < 4; ++i ) //喜好行走

    {

        if ( !inside(x + pgo[i][0], y + pgo[i][1]) ) continue;

        if ( better(x + pgo[i][0],y + pgo[i][1], xx, yy) )

            xx = x + pgo[i][0], yy = y + pgo[i][1];

    }

    x = xx, y = yy;

    int txx = tx + go[f2][0];

    int tyy = ty + go[f2][1];

    if ( inside(txx, tyy) ) tx = txx, ty = tyy; //宝藏走

    ++time;

    return false;

}



int main()

{

    int t = 0;

    while ( scanf("%d", &n), n )

    {

        if ( ++t > 1 ) printf("\n");

        Init();

        printf("Case %d:\n", t);

        while ( time < 100 )

        {

            if ( step() )

            {

                printf("Get the treasure! At step %d.\n", time);

                break;

            }

            if ( circle )

            {

                printf("Impossible. At step %d.\n", time);

                break;

            }

            if ( time == 99 ) printf("Not sure.\n");

        }

    }

    return 0;

}

 

G:Greatest Number

二分

H:Hello World!

一道水题,比赛的时候我和陈兴想多了,但还好陈兴用强大的STL功底过了。给出n个点x和y的值,找到每个点的行和列都比它大的点,优先选择行小的

作为结果,行相等则选择列小的。n^2可以暴力过。

我的代码:

#include <stdio.h>

#include <string.h>

#include <stdlib.h>



const int MAXN = 1 << 10;

const int INF = 0x3f3f3f3f;

int x[MAXN], y[MAXN];

int n;

int main()

{

    //freopen("hello.in", "r", stdin);

    //freopen("hello1.out", "w", stdout);

    int t = 1;

    while(scanf("%d", &n), n)

    {

        for(int i = 1; i <= n; i ++)

        {

            scanf("%d%d", &x[i], &y[i]);

        }

        if(t > 1) printf("\n");

        printf("Case %d:\n", t ++);

        int minx, miny;

        for(int i = 1; i <= n; i ++)

        {

            minx = miny = INF;

            for(int j = 1; j <= n; j ++)

            {

                if(i == j) continue;

                if(y[j] > y[i] && x[j] > x[i])

                {

                    if(minx > x[j])

                    {

                        minx = x[j], miny = y[j];

                    }

                    if(minx == x[j])

                    {

                        if(miny > y[j])

                        {

                            minx = x[j], miny = y[j];

                        }

                    }

                }

            }

            if(minx < INF && miny < INF)

            {

                printf("%d %d\n", minx, miny);

            }

            else

            {

                puts("-1 -1");

            }

        }

    }

    return 0;

}

陈兴的代码:

#include<cstdio>

#include<set>

#include<iterator>

#include<algorithm>

using namespace std;

const int MAXN = 1010;

struct Node

{

    int row, colum;

    int order;

    bool operator<(const struct Node ans) const

    {

        return (row < ans.row || (row == ans.row && colum < ans.colum));

    }

}node[MAXN];

struct Res

{

    int row, colum;

}resl[MAXN];

int n;

set<struct Node> myset;

bool cmp1(const struct Node ans1, const struct Node ans2)

{

    return ans1.row > ans2.row;

}

bool cmp2(const struct Node ans1, const struct Node ans2)

{

    return ans1.order < ans2.order;

}

void Init()

{

    for(int i = 0; i < n; i++)

    {

        scanf("%d%d", &node[i].row, &node[i].colum);

        node[i].order = i;

    }

    sort(node, node + n, cmp1);//行升序

}

void Solve()

{

    int tmp;

    myset.clear();

    for(int i = 0; i < n; i++)

    {

        tmp = node[i].order;

        resl[tmp].row = -1;

        resl[tmp].colum = -1;

        set<struct Node>::iterator it = myset.begin();

        while(it != myset.end())

        {

            if(it->row > node[i].row && it->colum > node[i].colum)

            {

                resl[tmp].row = it->row;

                resl[tmp].colum = it->colum;

                break;

            }

            it++;

        }

        myset.insert(node[i]);

    }

}

int main()

{

    int i = 1;

    while(scanf("%d", &n)!= EOF && n)

    {

        Init();

        Solve();

        if(i > 1) putchar('\n');

        printf("Case %d:\n", i++);

        for(int j = 0; j < n; j++)

        {

            printf("%d %d\n", resl[j].row, resl[j].colum);

        }

    }

    return 0;

}

I:Ivan comes again!

线段树离散化+set。

赛后殷神犇告诉我这道题我做过,我还不信,结果翻到了HDU 3627的代码,拍了下数据,0行差异,我只能表示呵呵。才多久就忘了做过这题...

/*Accepted    3627    1203MS    6848K    2698 B    C++*/

#include<cstdio>

#include<cstring>

#include<algorithm>

using namespace std;



const int MAXN = 200010;

struct TPoint{

    int x, y, flag;

}pre[MAXN], ans[MAXN], s;



char op[10];

int n, m;



struct Segtree

{

    int l, r, maxy;

}tree[MAXN << 2];



bool cmp(TPoint a, TPoint b)

{

    return a.x < b.x || ( a.x == b.x && a.y < b.y);

}



void build( int rt, int l, int r)

{

    tree[rt].l = l, tree[rt].r = r, tree[rt].maxy = -1;

    if( l == r) return;

    int m = (l + r) >> 1;

    build( rt << 1, l, m);

    build( rt << 1 | 1, m + 1, r);

}



int BS( TPoint nd, int l, int r)

{

    while( l <= r){

        int m = (l + r) >> 1;

        if( nd.x == ans[m].x && nd.y == ans[m].y) return m;

        if( nd.x < ans[m].x || nd.x == ans[m].x && nd.y < ans[m].y)

            r = m - 1;

        else l = m + 1;

    }

    return -1;

}



void update( int rt, int l, int flag)

{

    if( tree[rt].l == l && tree[rt].r == l)

    {

        if( 1 == flag)

            tree[rt].maxy = ans[l].y;

        if( 2 == flag)

            tree[rt].maxy = -1;

        return;

    }

    int m = (tree[rt].l + tree[rt].r) >> 1;

    if(l <= m) update( rt << 1, l, flag);

    else update( rt << 1 | 1, l, flag);

    tree[rt].maxy = max( tree[rt << 1].maxy, tree[rt << 1 | 1].maxy);

}



void query(int rt, TPoint nd)

{

    if(tree[rt].maxy <= nd.y) return;

    if(ans[tree[rt].r].x <= nd.x) return;

    if( tree[rt].l == tree[rt].r){

        s = ans[tree[rt].l]; return;

    }

    query(rt << 1, nd);

    if(s.x == -1) query(rt << 1 | 1, nd);

}



void prepare()

{

    int i;

    for( i = 1, m = 0; i <= n; i ++)

    {

        scanf( "%s%d%d", op, &pre[i].x, &pre[i].y);

        if('a' == op[0]) {

            pre[i].flag = 1;

            ans[++ m] = pre[i];

        }

        else if( 'r' == op[0]) pre[i].flag = 2;

        else pre[i].flag = 3;

    }

    sort( ans + 1, ans + m + 1, cmp);

    build( 1, 1, m);

}



void operation()

{

    for( int i = 1; i <= n; i ++)

    {

        int cnt = BS(pre[i], 1, m);

        if( 3 == pre[i].flag)

        {

            s.x = s.y = -1;

            query( 1, pre[i]);

            if( s.x == -1) printf( "-1\n");

            else printf( "%d %d\n", s.x, s.y);

        }

        else{

            update( 1, cnt, pre[i].flag);

        }

    }

}



int main()

{

    //freopen("Ivan.in", "r", stdin);

    //freopen("Ii.out", "w", stdout);

    int cas = 0;

    while( scanf( "%d", &n), n)

    {

        if( cas ++) printf( "\n");

        printf( "Case %d:\n", cas);

        prepare();

        operation();

    }

    return 0;

}

 

J:Jerry Mouse

题目很长,当时没看,后面大神们说是并查集,其他队都在比赛中A掉了。

你可能感兴趣的:(a)