WAhaha_hnu (zoj 2010 oct月赛)

官方解题报告 http://blog.watashi.ws/1515/zojmonthly1010/

A题  签到题,╮(╯▽╰)╭,因为 int -> char* 错了一次,还是很粗心。

View Code
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<string>

using namespace std;

const int N = 101100;
char str[N];


bool isch( char ch ){
    if( (ch>='a'&&ch<='z') || (ch>='A'&&ch<='Z') )
        return true;
    return false;
}
string get_str( int x ){
    
    string tmp;
    char sa[1010];    
    int len = 0;
    while( x ){
        sa[len++] = x%10 + '0'; x /= 10;
    }
    for(int i = len-1; i >= 0; i-- )
        tmp += sa[i];
    return tmp;
}
int main(){
    while( gets( str) ){
        if( strcmp( str, "EOF" ) == 0 ) break; 

        //printf("str = %s", str );    
        int len = strlen(str), n = 0, i = 0;
        string s;    
        
        while( i < len )    
        {
            if( isch( str[i] ) ){

                s += str[i];

                int t = i+1;
                while( isch(str[t]) && (t<len) ) ++t;
                t--;

                if( t-i >= 1 ){
                    if( t-i >= 2 )    
                        s += get_str( t-i-1 );
                    s += str[t];    
                }    
                i = t+1;    
            }    
            else    s += str[i++];
        }
        printf("%s\n", s.c_str() );    
    }
    return 0;
}

B题  一开始理解错题意,粗心一路到底啊~~

  假设横切为x,纵切为y,克隆为a, 则对于总分数n,以及操作次数m,共有

    2*x*(y+1) + a = n

    x + y + a = m 

  两式联立可得 x, y 的计算式, 因为 n,m 都比较大, 但是 x*y <= n => x <= sqrt(n) || y <= sqrt(n)

  所以我们可以通过分别枚举 x,y 到sqrt(n) 来得出结果, 因为 x,y对称,所以可以在一个循环内得出。

  另外,以上两式的成立条件是在 x > 0 的前提下, 所以当 x = 0,时候要特判,还有当 n <= m 时也要特判。

View Code
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#define MIN(a,b) (a)<(b)?(a):(b)
typedef long long LL;

int main(){

    int n, m, T;
    scanf("%d", &T);

    while( T-- )
    {
        scanf("%d %d", &n,&m);
        if( n <= m ){
            printf("-1\n");
            continue;
        }    
        if( n-1 == m ){
            printf("0\n");
            continue;
        }    
        bool flag = false;
        int res = m+1;
        int Max = sqrt(n)+1;    
        for(int x = 0; x <= Max; x++ )
        {
            int ta = n-m-x, tb = 2*x-1;    
            if( ta%tb == 0 ){
                int y = ta/tb;
                if( (y>=0) && (x+y<=m) ){    
                    flag = true;    
                    res = MIN( res, m-x-y );    
                }    
            }
            ta = n-m+x; tb = 2*x+1;
            if( ta%tb == 0 ){
                int y = ta/tb;
                if( (y >=0) && (x+y<=m) ){
                    flag = true;
                    res = MIN( res, m-x-y);
                }
            }
        }    
        if( flag )  printf("%d\n", res );
        else    printf("-1\n");
    }
    return 0;
}

E题 看题后第一眼想到DP, 但是时间复杂度无法承受,然后就没管了,回头细想下,觉得贪心应该还是能过的... 越学越笨了~~~

  题目未限定通过陷阱顺序, 通过将陷阱按照 D 排序后, 依次处理,若累积时间 T <= Di 则拆除过去,否则失血,此时选择 [1,i]区间

中时间消耗最大的,这里使用优先队列 来维护。

View Code
#include<iostream>
#include<cstdio>
#include<cstring> 
#include<queue>
#include<algorithm>
using namespace std;
const int N = 25010;

pair<int,int> p[N];

int n, k;

int main(){
    while( scanf("%d%d", &n,&k) != EOF)
    {
        for(int i = 0; i < n; i++)
            scanf("%d%d", &p[i].second,&p[i].first );
        sort( p, p+n );
        int T = 0, hp = 0;
        priority_queue< int > Q;
        
        for(int i = 0; i < n; i++ ){
            T += p[i].second;
            Q.push( p[i].second );
            while( T > p[i].first ){
                T -= Q.top(); Q.pop();
                hp++;
            }    
        }
        if( hp < k ) printf("%d\n", hp );
        else printf("-1\n");
    }
    return 0;    
}

I题 ╮(╯▽╰)╭,比赛时看题能力还是不够,错把题目看成是 折现上的点 相邻的直接距离了。

  计算折线总长度后,得到点间距离,然后从起点开始模拟查找就可以得出结果了。

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