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