hut_csust 训练赛第三场 解题报告

题目链接: www.acmore.net

 

Problem A

  遍历数组a, 对于每一个元素 a[i], 统计区间 ( a[i], a[i]+d ] 有X个点,则符合条件的为 C(2,X) 

  累加就可以了

解题代码

View Code
#include<stdio.h>

#include<string.h>

#include<iostream>

#include<algorithm>

#include<vector>

#include<map>

using namespace std;





typedef long long LL;

const int N = 1e5+10;

const int M = 1e6;

map< LL, int > Mp;





int n, C[M+10], size;

LL a[N], d, b[M];

void update( int x )

{

    for(; x <= M; x += (x&(-x)) )

            C[x] += 1; 

}

int read( int x )

{

    int res = 0;

    for( ; x >= 1; x -= (x&(-x))  )

        res += C[x];

    return res;

}

int main()

{

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

    {

        Mp.clear();

        size = 0;    

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

        {

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

            b[size++] = a[i];

            b[size++] = a[i]+d;

        }        

        sort( b, b+size );

        size = unique( b, b+size) - b;

        int tmp = 1;

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

            Mp[ b[i] ] = tmp++;



        memset( C, 0, sizeof(C));

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

            update( Mp[ a[i] ] );

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

        {

            int k = read( Mp[ a[i]+d ] ) - (i+1);    

            if( k > 1 )    

                ans += 1LL*k*(k-1)/2;

        }

        printf("%lld\n", ans );    

    }

    return 0;

}

 

Problem B

  字符串处理,取最长的,当有多个,则字典序最大的是结果

解题代码

View Code
#include<stdio.h>

#include<string.h>

#include<stdlib.h>

#include<vector>

#include<iostream>

#include<algorithm>

using namespace std;



char str[110][110];



vector< string > S;

int main()

{

    int n;

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

    {

        int L = 0;

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

        {

            scanf("%s", str[i] );

            if( strlen( str[i] ) > L ) 

                L = strlen(str[i]);

        }

        S.clear();    

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

            if( strlen(str[i]) == L ) 

                    S.push_back( str[i] );

        sort( S.begin(), S.end() );    

        printf("%s\n", (S[ S.size()-1 ]).c_str() );

    }

    return 0;

}

 

Problem C

  递推, F(N) = F(N-1)+ F(N-2)

解题代码

View Code
#include<stdio.h>



typedef long long LL;



LL f[55] = {1,1,2};



int main()

{

    for(int i = 3; i <= 50; i++)

            f[i] = f[i-1]+f[i-2];

    int a, b, T;

    scanf("%d", &T);

    while( T-- && scanf("%d%d", &a,&b) )

        printf("%lld\n", f[b-a] );

    return 0;

}

 

Problem D

  枚举长度O(N),之后枚举左边界O(N), 使用差值取模O( LogN ) 判定, 总时间复杂度为 O( N*N*LogN)

解题代码

View Code
#include<stdio.h>

#include<stdlib.h>

#include<string.h>





typedef unsigned long long LL;



char s1[1010];

int n;

LL A[1010],B[1010], C[2][2020], T[1010];





void add(int key, int x, LL val )

{

    for(; x <= 1000; x+=(x&(-x)))

            C[key][x] += val;

}

LL read(int key, int x)

{

    LL res = 0;

    for(; x >= 1; x -= (x&(-x)) )

        res += C[key][x];

    return res;

}

void init()

{

    A[0] = B[0] = 0;

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

    {

        A[i] = (s1[i]-'a'+1)*T[i-1];    

        B[i] = (s1[n+1-i]-'a'+1)*T[i-1];

    }    

    memset( C, 0, sizeof(C));

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

    {

        add( 0, i, A[i] );

        add( 1, i, B[i] );

    }

}

int find( int len )

{

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

    {

        int a = i, b = i+len-1;    

        int c = (n+1)-b, d = (n+1)-a;    

        LL sa = read(0,b)-read(0,a-1);

        LL sb = read(1,d)-read(1,c-1);

        sa *= T[c-1]; sb *= T[a-1];

        if( sa == sb )     return i;

    }

    return -1;

}

int main()

{

    T[0] = 1;

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

        T[i] = T[i-1]*27;



    while( scanf("%s", s1+1) != EOF)

    {

        n = strlen(s1+1);    

        

        init();    

        for(int m = n; m >= 1; m-- )

        {

            int s = find(m);    

            if( s != -1 )

            {

                for(int i = s; i < s+m; i++)

                    printf("%c", s1[i]); puts("");

                break;

            }    

        }

    }

    return 0;

 }

 

Problem E

  按分数排序

解题代码

View Code
#include<stdio.h>

#include<string.h>

#include<algorithm>

#include<iostream>

#include<stdlib.h>

using namespace std;



const int N = 5150;

struct node

{

    char name[30];

    double score;

    bool operator < ( node tmp ) const

    {

        return score > tmp.score;    

    }

    void read( )

    {

            scanf("%s %lf", name, &score );    

    }

}stu[N];



int n, r;

char str[30];



int main()

{

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

    {

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

            stu[i].read();

        sort( stu, stu+n );

        

        scanf("%d", &r);

        while( r-- )

        {

            scanf("%s", str );    

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

                if( strcmp( stu[i].name, str ) == 0 )

                {

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

                    break;

                }

        }    

    }

    return 0;

}

 

Problem F

  BFS广搜即可,因为每个点至多走一次,也才10*10. 注意起点也算1步

解题代码

View Code
#include<stdio.h>

#include<string.h>

#include<stdlib.h>

#include<iostream>

#include<queue>

using namespace std;







char map[15][15];

int n, m, s;

int vis[15][15];

struct node

{

    int x, y;

    int step;

}info,nxt;



bool legal(int x, int y)

{

    if( x >= 1 && x <= n && y >= 1 && y <= m )

        return true;

    return false;

}

void getdir( int x1, int y1, int &x, int &y )

{

    switch( map[x1][y1] )

    {

        case 'W': 

            x = x1;

            y = y1-1;

            break;

        case 'E':

            x = x1;

            y = y1+1;

            break;

        case 'N':

            x = x1-1;

            y = y1;

            break;

        case 'S':

            x = x1+1;

            y = y1;

            break;

    }

}

queue<node> Q;

void solve()

{

    memset( vis , 0, sizeof(vis) );

    while( !Q.empty() ) Q.pop();

    info.x = 1; info.y = s;

    info.step = 1;

    Q.push(info);

    vis[info.x][info.y] = 1;

    while( !Q.empty() )

    {

        info = Q.front(); Q.pop();

        

            int x, y;

            getdir( info.x,info.y,x,y);    

            if( !legal(x,y) )

            {

                printf("%d step(s) to exit\n",info.step);     

                return;    

            }

            else if( vis[x][y] )

            {

                printf("%d step(s) before a loop of %d step(s)\n", vis[x][y]-1, info.step-vis[x][y]+1);

                return;    

            }

            else

            {

                vis[x][y] = info.step+1;

                nxt.step = info.step+1;

                nxt.x = x; nxt.y = y;

                Q.push(nxt);    

            }

    }

}

int main()

{

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

    {

        if( !(n+m+s) ) break;    

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

            scanf("%s", map[i]+1);

        solve();

    }

    return 0;

}

 

Problem G

  位运算,异或, 当都为1时才为1,否则为0 

  初始令X = 0, 与所有数异或,那么相同的数,偶数个后都会为0,剩下的就是奇数个的值

  注意,后台数据貌似没有 N=0,所以结束条件为 EOF,否则会TLE

解题代码

View Code
#include<stdio.h>



int main()

{

    int n;

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

    {

        if( n == 0 ) break;    

        int a, x = 0;

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

        {    scanf("%d", &a); x ^= a; }

        printf("%d\n", x);    

    }

    return 0;

}

 

Problem H

  11年网络赛立体空间的简单版.

  枚举两个水果成直线,然后扫其他水果. 利用叉积判定是否在直线上.

  注意 坐标为 double类型. WA在了这上面

解题代码

View Code
#include<stdio.h>

#define max(x,y) (x)>(y)?(x):(y)

#define min(x,y) (x)<(y)?(x):(y)

const int inf=0x7fffffff;

typedef long long LL;



struct node      // Fruit

{

    double x,y;     

    void read( )

    {

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

    }

}Q[1010];



const double esp = 1e-8;

int sign(double x )

{

    return (x<-esp)? -1 : (x>esp);

}

bool judge( double x1,double y1,double x2,double y2,double x,double y )

{

         if( ( sign( ( x1-x )*( y2-y ) - ( x2-x )*( y1-y ) )) == 0 )

                return true;

         return false;

}

int n;



int main()

{

    int T;

    scanf("%d", &T);

    for(int Case = 1; Case <= T; Case++ )    

    {

        scanf("%d", &n);

        int ans = 1;

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

            Q[i].read();

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

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

            {

                int cnt = 2;    

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

                {

                    if( judge( Q[i].x, Q[i].y, Q[j].x, Q[j].y, Q[k].x, Q[k].y ) )

                        cnt++;

                }

                ans = max( ans, cnt );    

            }

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

    }

    return 0;

}

 

Problem I

  按要求使用栈模拟即可.

解题代码

View Code
#include<stdio.h>

#include<stdlib.h>

#include<string.h>

#include<algorithm>

#include<queue>

#include<stack>

#include<iostream>

using namespace std;



stack<string> s1, s2;



string op, web, cur;

int main()

{

    int Case = 1;

    while( cin>>op )

    {

        while( !s1.empty() ) s1.pop();

        while( !s2.empty() ) s2.pop();

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

        cur = "http://www.acmore.net/"; 

        cout << cur << endl;    

        while( cin>>op )

        {

    //        cout << "op = " << op << endl;    

            if( op == "end" )

            {

                cout << "end" << endl;    

                break;

            }    

            else if(  op ==  "visit"   )

            {

                cin >> web;    

    //            cout << "web = " << web << endl;    

                while( !s2.empty() ) s2.pop();    

                s1.push( cur );

                cur = web;    

                cout << cur << endl;    

            }

            else if(  op == "back" )

            {

                if( !s1.empty()  )

                {

                    s2.push( cur );

                    cur = s1.top(); s1.pop(); 

                    cout << cur << endl;    

                }

                else

                    cout << "This is the first page" << endl;

            }

            else if(  op == "forward" )

            {

                if( !s2.empty() )

                {

                    s1.push( cur );

                    cur = s2.top(); s2.pop();

                    cout << cur << endl;    

                }

                else

                    cout << "This is the last page" << endl;

            }

        }

    }

    return 0;

}

 

Problem J

  模拟题.....

解题代码 

View Code
#include <cstdio>

#include <cstring>

#include <cstdlib>

#include <iostream>

using namespace std;



int num[10];

char G[1000][1000];



int main() {

    int N, M;

    while (scanf("%d %d", &N, &M), N|M) {

        memset(num, 0, sizeof (num));

        for (int i = 0; i <= N*5; ++i) {

            scanf("%s", G[i]);

        }

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

            for (int j = 0; j < M; ++j) {

                int cnt = 0;

                int l = i*5+1, r = i*5+4, u = j*5+1, d = j*5+4; 

                for (int p = l; p <= r; ++p) {

                    for (int q = u; q <= d; ++q) {

                        if (G[p][q] == '*') {

                            ++cnt; 

                        }

                    }

                }

                num[cnt/4]++;

            }

        }

        for (int i = 0; i < 5; ++i) {

            printf(i == 0 ? "%d" : " %d", num[i]); 

        }

        puts("");

    }

    return 0; 

}

 

 

  

你可能感兴趣的:(su)