ACM 群赛

点此打开链接

A - 1
Time Limit:2000MS     Memory Limit:65536KB     64bit IO Format:%lld & %llu
Appoint description: 

Description

Complete the ternary calculation.

Input

There are multiple test cases. The first line of input contains an integer T indicating the number of test cases. For each test case:

There is a string in the form of "number1operatoranumber2operatorbnumber3". Each operator will be one of {'+', '-' , '*', '/', '%'}, and each number will be an integer in [1, 1000].

Output

For each test case, output the answer.

Sample Input

5
1 + 2 * 3
1 - 8 / 3
1 + 2 - 3
7 * 8 / 5
5 - 8 % 3

Sample Output

7
-1
0
11
3
Note

The calculation "A % B" means taking the remainder of A divided by B, and "A / B" means taking the quotient.

#include <stdio.h>
int priority ( char ch )
{
    if ( ch == '+' || ch == '-' )
        return 1;
    return 2;
}
int oper ( int a, int b, char ch )
{
    switch ( ch )
    {
        case '+' : return a+b;
        case '-' : return a-b;
        case '*' : return a*b;
        case '/' : return a/b;
        case '%' : return a%b;
    }
}
int main ( )
{
    int T, a, b, c;
    char op1[2], op2[2];
    scanf ( "%d", &T );
    while ( T -- )
    {
        scanf ( "%d%s%d%s%d", &a, op1, &b, op2, &c );
        int p1 = priority ( op1[0] );
        int p2 = priority ( op2[0] );
        if ( p1 >= p2 )
            printf ( "%d\n", oper ( oper ( a, b, op1[0] ), c, op2[0] ) );
        else
            printf ( "%d\n", oper ( a, oper ( b, c, op2[0] ), op1[0] ) );
    }
    return 0;
}

problem B

http://blog.csdn.net/wsnbb123456789/article/details/50767456


LightOJ 1089

Description

Given n segments (1 dimensional) and q points, for each point you have to find the number of segments which contain that point. A point pi will lie in a segment A B if A ≤ pi ≤ B.

For example, if the segments are (6 12), (8 8), (10 12), (8 11), (0 12) and the point is 11, then it is contained by 4 segments.

Input

Input starts with an integer T (≤ 5), denoting the number of test cases.

Each case starts with a line containing two integers n (1 ≤ n ≤ 50000) and q (1 ≤ q ≤ 50000).

Each of the next n lines contains two integers Ak Bk (0 ≤ Ak ≤ Bk ≤ 108) denoting a segment.

Each of the next q lines contains an integer denoting a point. Each of them range in [0, 108].

Output

For each case, print the case number in a single line. Then for each point, print the number of segments that contain that point.

Sample Input

1

5 4

6 12

8 8

10 12

8 11

0 12

11

12

2

20

Sample Output

Case 1:

4

3

1

0


此题明显可以用线段树和树状数组做,就是对所有出现的点包括查询的点,保存、排序、去重,然后更新就可以了。

#include <stdio.h>
#include <algorithm>
#include <string.h>
#define lson l, m, rt << 1
#define rson m+1, r, rt << 1 | 1
const int maxn = 50005, N = maxn*3; //N为3倍
int A[maxn], B[maxn], Q[maxn], point[N];
int sum[N << 2], tag[N << 2];
void PushDown ( int rt, int m )
{
    if ( tag[rt] )
    {
        tag[rt << 1] += tag[rt];
        tag[rt << 1 | 1] += tag[rt];
        sum[rt << 1] += ( m-( m >> 1 ) )*tag[rt];
        sum[rt << 1 | 1] += ( m >> 1 )*tag[rt];
        tag[rt] = 0;
    }
}
void update ( int L, int R, int v, int l, int r, int rt )
{
    if ( L <= l && r <= R )
    {
        sum[rt] += ( r-l+1 )*v;
        tag[rt] += v;
        return ;
    }
    PushDown ( rt, r-l+1 );
    int m = ( l+r ) >> 1;
    if ( L <= m )
        update ( L, R, v, lson );
    if ( R > m )
        update ( L, R, v, rson );
}
int query ( int q, int l, int r, int rt )
{
    if ( l == r )
        return sum[rt];
    PushDown ( rt, r-l+1 );
    int m = ( l+r ) >> 1;
    if ( q <= m )
        return query ( q, lson );
    else
        return query ( q, rson );
}
int Bin ( int x, int l, int r )
{
    int m;
    while ( l <= r )
    {
        m = ( l+r ) >> 1;
        if ( point[m] == x )
            return m;
        if ( point[m] > x )
            r = m-1;
        else
            l = m+1;
    }
    return 0;
}
void solve ( )
{
    int T, n, q, cas = 1;
    scanf ( "%d", &T );
    while ( T -- )
    {
        scanf ( "%d%d", &n, &q );
        int cnt = 0;
        for ( int i = 0; i < n; i ++ )
        {
            scanf ( "%d%d", &A[i], &B[i] );
            point[cnt ++] = A[i];
            point[cnt ++] = B[i];
        }
        for ( int i = 0; i < q; i ++ )
        {
            scanf ( "%d", &Q[i] );
            point[cnt ++] = Q[i];
        }
        std :: sort ( point, point+cnt );
        int k = 1;
        for ( int i = 1; i < cnt; i ++ )
            if ( point[i] != point[i-1] )
                point[k ++] = point[i];
        memset ( sum, 0, sizeof ( sum ) );
        memset ( tag, 0, sizeof ( tag ) );
        for ( int i = 0; i < n; i ++ )
        {
            int l = Bin ( A[i], 0, k-1 );
            int r = Bin ( B[i], 0, k-1 );
            update ( l, r, 1, 0, k-1, 1 );
        }
        printf ( "Case %d:\n", cas ++ );
        for ( int i = 0; i < q; i ++ )
        {
            int p = Bin ( Q[i], 0, k-1 );
            printf ( "%d\n", query ( p, 0, k-1, 1 ) );
        }
    }
}
int main ( )
{
    solve ( );
    return 0;
}
树状数组代码——更新可以看第四题的讲解

#include <stdio.h>
#include <algorithm>
#include <string.h>
const int maxn = 50005, N = maxn*3;
int A[maxn], B[maxn], Q[maxn], point[N];
int sum[N], k;
int Bin ( int x, int l, int r )
{
    int m;
    while ( l <= r )
    {
        m = ( l+r ) >> 1;
        if ( point[m] == x )
            return m;
        if ( point[m] > x )
            r = m-1;
        else
            l = m+1;
    }
    return 0;
}
inline int lowbit ( int x )
{
    return x & -x;
}
void add ( int x, int v )
{
    while ( x < k )
    {
        sum[x] += v;
        x += lowbit ( x );
    }
}
int bit_sum ( int x )
{
    int res = 0;
    while ( x > 0 )
    {
        res += sum[x];
        x -= lowbit ( x );
    }
    return res;
}
void solve ( )
{
    int T, n, q, cas = 1;
    scanf ( "%d", &T );
    while ( T -- )
    {
        memset ( sum, 0, sizeof ( sum ) );
        scanf ( "%d%d", &n, &q );
        int cnt = 1;
        for ( int i = 0; i < n; i ++ )
        {
            scanf ( "%d%d", &A[i], &B[i] );
            point[cnt ++] = A[i];
            point[cnt ++] = B[i];
        }
        for ( int i = 0; i < q; i ++ )
        {
            scanf ( "%d", &Q[i] );
            point[cnt ++] = Q[i];
        }
        std :: sort ( point+1, point+cnt );
        k = 2;
        for ( int i = 2; i < cnt; i ++ )
            if ( point[i] != point[i-1] )
                point[k ++] = point[i];
        memset ( sum, 0, sizeof ( sum ) );
        for ( int i = 0; i < n; i ++ )
        {
            int l = Bin ( A[i], 1, k-1 );
            int r = Bin ( B[i], 1, k-1 );
            add ( l, 1 );
            add ( r+1, -1 );    //更新[l,r]的总个数为1,超过r和抵消
        }
        printf ( "Case %d:\n", cas ++ );
        for ( int i = 0; i < q; i ++ )
        {
            int p = Bin ( Q[i], 0, k-1 );
            printf ( "%d\n", bit_sum ( p ) );   //直接查询
        }
    }
}
int main ( )
{
    solve ( );
    return 0;
}

Problem D

http://blog.csdn.net/wsnbb123456789/article/details/50767516


Problem E(链接:https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=2674)


题意:

在一场滑雪比赛中要通过n个门,给出每个门的坐标(xi,yi)。数据给出w(每个门的宽度),v(水平方向上的最大速度,即x轴),以及n。然后是n行门的坐标。在给出m,表示有m双滑雪鞋,每双鞋的速度为s[i]。问说可以通过所有旗门的滑雪板的最大速度。

首先可以知道速度可能有重复的,所以可以排序去重,然后二分,当取某个速度使所有门都能穿过时就表示此速度可行,假设第一个门可通过,第一个门的x范围就可以知道,

后面的范围可以通过能走到的x的最远距离算出下一个x范围,如果有交集证明都能走到,没有交集即此速度无法穿过所有门。

最远距离:

知道垂直距离dy,水平最大速度v,一个假设的垂直速度x,平抛运动可以知道垂直时间和水平运动时间一样的

那么:x*t = dy

   v*t = dist

所以dist = dy*v/x,算出最大距离就可以确定区间。


#include <stdio.h>
#include <algorithm>
#include <utility>
using namespace std;
typedef pair < int, int > P;
const int maxn = 100005;
int a[maxn*10], ans, n, w, v;
P cor[maxn];
int is_ok ( int x )
{
    double l = cor[0].first*1.0, r = cor[0].first*1.0+w;
    for ( int i = 1; i < n; i ++ )
    {
        double dist = ( cor[i].second-cor[i-1].second )*1.0*v/x;
        /*
            dy = cor[i].second-cor[i-1].second
            速度为x
            dx = ?
            速度为v
            因为下滑时间和水平移动时间相等(平抛运动)
            x*t = dy
            v*t = dx
        */
        l = max ( l-dist, cor[i].first*1.0 );
        r = min ( r+dist, cor[i].first*1.0+w ); //其余区间的交集
        if ( l > r )    //交集为空
            return 0;
    }
    return 1;
}
void Bin ( int l, int r )
{
    int m;
    while ( l <= r )
    {
        m = ( l+r ) >> 1;
        if ( is_ok ( a[m] ) )
        {
            ans = m;
            l = m+1;
        }
        else
            r = m-1;
    }
}
void solve ( )
{
    int T, s;
    scanf ( "%d", &T );
    while ( T -- )
    {
        scanf ( "%d%d%d", &w, &v, &n );
        for ( int i = 0; i < n; i ++ )
            scanf ( "%d%d", &cor[i].first, &cor[i].second );
        scanf ( "%d", &s );
        for ( int i = 0; i < s; i ++ )
            scanf ( "%d", &a[i] );
        sort ( a, a+s );
        int k = 1;
        for ( int i = 1; i < s; i ++ )
            if ( a[i] != a[i-1] )
                a[k ++] = a[i];
        ans = -1;
        Bin ( 0, k-1 );
        if ( ans == -1 )
            printf ( "IMPOSSIBLE\n" );
        else
            printf ( "%d\n", a[ans] );
    }
}
int main ( )
{
    solve ( );
    return 0;
}

F - 6
Time Limit:1000MS     Memory Limit:131072KB     64bit IO Format:%lld & %llu
Appoint description: 

Description

现在有n堆果子,第i堆有ai个果子。现在要把这些果子合并成一堆,每次合并的代价是两堆果子的总果子数。求合并所有果子的最小代价。

Input

第一行包含一个整数T(T<=50),表示数据组数。
每组数据第一行包含一个整数n(2<=n<=1000),表示果子的堆数。
第二行包含n个正整数ai(ai<=100),表示每堆果子的果子数。

Output

每组数据仅一行,表示最小合并代价。

Sample Input

2
4
1 2 3 4
5
3 5 2 1 4

Sample Output

19
33

此题并没有要求相邻才能合并,所以就是赫夫曼思想,用优先队列取两个最小值统计和,并将此两个最小值的和push。

#include <stdio.h>
#include <queue>
using namespace std;
void solve ( )
{
    priority_queue < int, vector < int >, greater < int > > q;
    int T, n, v;
    scanf ( "%d", &T );
    while ( T -- )
    {
        scanf ( "%d", &n );
        for ( int i = 0; i < n; i ++ )
        {
            scanf ( "%d", &v );
            q.push ( v );
        }
        int ans = 0;
        while ( !q.empty ( ) )
        {
            int a = q.top ( );
            q.pop ( );
            if ( q.empty ( ) )
                break ;
            int b = q.top ( );
            q.pop ( );
            ans += a+b;
            q.push ( a+b );
        }
        printf ( "%d\n", ans );
    }
}
int main ( )
{
    solve ( );
    return 0;
}


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值