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

  

原文地址:https://www.cnblogs.com/yefeng1627/p/2846507.html