A - Lala Land and Apple Trees 在一维直线上有一些苹果树,上面有一些苹果,从坐标处为0的点出发,向左或向右,每次遇到没摘的苹果树就摘光苹果然后掉头。问最多能摘多少苹果。
int n;
struct node{
int a, p;
}v1[321], v2[321];
bool cmp( node q, node w )
{
if( q.p > w.p )
return 1;
return 0;
}
int main()
{
while( ~scanf("%d", &n) ) {
int a, p, cnt1 = 0, cnt2 = 0;
for( int i = 1; i <= n; ++i ) {
scanf("%d%d", &p, &a);
if( p < 0 )
v1[cnt1].a = a, v1[cnt1++].p = p;
else
v2[cnt2].a = a, v2[cnt2++].p = p;
}
sort( v1, v1+cnt1, cmp );
sort( v2, v2+cnt2, cmp );
int m = min( cnt1, cnt2 );
int ans = 0;
for( int i = 0; i < m; ++i ) {
ans += v1[i].a;
ans += v2[cnt2-1-i].a;
}
if( cnt1 < cnt2 )
ans += v2[cnt2-1-m].a;
else if( cnt1 > cnt2 )
ans += v1[m].a;
printf("%d\n", ans);
}
return 0;
}
B - Amr and The Large Array给出一个数组,找出出现次数最多的那个数的左右两边,若长度相同则使长度尽量短
vector <int> v[N];
int main()
{
int n, x;
scanf("%d", &n);
for( int i = 1; i <= n; ++i) {
scanf("%d", &x);
v[x].push_back(i);
}
int maxx = 0, l, r, len = inf;
for( int i = 1; i <= 1000000; ++i ){
if( v[i].size() > maxx ) {
maxx = v[i].size();
sort( v[i].begin(), v[i].end() );
l = v[i][0], r = v[i][v[i].size()-1];
len = r - l + 1;
}
else if( v[i].size() == maxx ) {
if( maxx == 0 )
continue;
sort( v[i].begin(), v[i].end() );
int ll = v[i][0], rr = v[i][v[i].size()-1];
if( rr - ll + 1 < len ) {
len = rr - ll + 1;
l = ll;
r = rr;
}
}
}
cout << l << " " << r << endl;
return 0;
}
C - Amr and Chemistry 给出n种物品的数量,每次数量能*2 或/2,问使所有物品数量一样的最小操作数。
暴力枚举每种数量能达到的值及操作数,然后枚举并更新。注意若x能整除2那么x/2就不必向上扩展了
const int N = 100010;
queue <pair <int, int> > q;
int n;
int a[N];
pair<int, int> Hash[N];
int main()
{
while( ~scanf("%d", &n) ) {
for( int i = 1; i <= n; ++i ) {
scanf("%d", &a[i]);
Hash[i].first = Hash[i].second = 0;
}
for( int i = 1; i <= n; ++i ) {
int x = a[i], cnt = 0;
while( !q.empty() ) q.pop();
q.push( Mp(x, cnt) );
int sum = 0;
while( x/2 >= 1 ) {
cnt++;
if( x & 1 ) {
q.push( Mp( x/2, cnt ) );
}
else {
Hash[x/2].first++;
Hash[x/2].second += cnt;
}
x /= 2;
}
while( !q.empty() ) {
pair <int, int> t = q.front();
q.pop();
while( t.first < N ) {
Hash[t.first].first++;
Hash[t.first].second += t.second;
t.first <<= 1;
t.second++;
}
}
}
int ans = inf;
for( int i = 1; i <= N; ++i ) {
if( Hash[i].first < n )
continue;
//printf("%d\n", Hash[i].second);
ans = min( ans, Hash[i].second );
}
printf("%d\n", ans);
}
return 0;
}
D - Guess Your Way Out! II 给出一颗完全二叉树,每次给出了 l, r, op,op = 1表示出口在【l,r】这颗子树包含的最下层叶子节点里面,或者op = 0表示出口不在【l,r】这颗子树的最下层叶子节点里。问最后是否最下层叶子节点是否有一个确定的出口。
每次将更新都表示在最下层叶子节点上面,将op=1的操作不断与之前的区间交最后得到一个确定的区间(若区间有多个那么就说明cheat),而将op=0的操作保存起来,最后与之前处理出来的区间进行更新,最后看确定的区间的数量和是否只有一个点,根据结果输出答案即可
const int N = 100010;
ll query, h;
struct node{
ll l, r;
bool operator < ( const node &rhs ) const {
if( l == rhs.l )
return r > rhs.r;
return l < rhs.l;
}
}a[N];
vector <node> v;
int main()
{
while( ~scanf("%lld%lld", &h, &query) ) {
v.clear();
ll le, l, r, f, cnt = 0;
bool cheat = 0;
ll L = (1LL << (h - 1)), R = (1LL << h) - 1;
while( query-- ) {
scanf("%lld%lld%lld%lld", &le, &l, &r, &f);
if( cheat )
continue;
l = l * (1LL<<(h-le));
r = (r+1) * (1LL<<(h-le)) - 1;
if( f ) {
if( l > R || r < L ) {
cheat = 1;
continue;
}
else {
L = max( L, l );
R = min( R, r );
}
}
else {
node tmp;
tmp.l = l, tmp.r = r;
a[++cnt] = tmp;
}
}
if( cheat ) {
puts("Game cheated!");
continue;
}
sort( a+1, a+cnt+1 );
f = 1;
for( int i = 1; i <= cnt; ++i ) {
ll l = a[i].l, r = a[i].r;
if( L > R ) {
f = 0;
break;
}
if( l > R )
break;
if( r < L )
continue;
if( l <= L && R <= r ) {
f = 0;
break;
}
if( L <= l && r <= R ) {
node tmp;
tmp.l = L, tmp.r = l-1;
if( tmp.l <= tmp.r )
v.push_back(tmp);
L = r + 1;
continue;
}
if( L <= l && R <= r ) {
node tmp;
tmp.l = L, tmp.r = l-1;
if( tmp.l <= tmp.r )
v.push_back(tmp);
f = 0;
break;
}
if( l <= L && r <= R )
L = r+1;
}
if( L <= R && f ) {
node tmp;
tmp.l = L, tmp.r = R;
v.push_back(tmp);
}
int sz = v.size();
if( sz == 0 )
puts("Game cheated!");
else if( sz >= 2 || ( sz == 1 && v[0].r > v[0].l ) )
puts("Data not sufficient!");
else
printf("%lld\n", v[0].l);
}
return 0;
}
E - A Simple Task 给出一个字符串,每次选出一段子区间,使得里面的字符升序或者降序重新排。操作完输出最后的结果。
开26颗线段树,每棵树保存对应从a~z的字符在某段区间的数量,每次操作的时候都相应的先删去那段操作区间的值,然后根据排的结果重新确定相应区间内该字符的数量。最后一次查询输出结果。
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <vector>
#include <string>
#include <math.h>
#include <time.h>
#include <stdio.h>
#include <iomanip>
///cout << fixed << setprecision(13) << (double) x << endl;
#include <stdlib.h>
#include <string.h>
#include <iostream>
#include <algorithm>
using namespace std;
#define lson l, mid, rt << 1
#define rson mid + 1, r, rt << 1 | 1
#define ls rt << 1
#define rs rt << 1 | 1
#define pi acos(-1.0)
#define eps 1e-8
#define asd puts("sdfsdfsdfsdfsdfsdf");
#define Mp(a, b) make_pair(a, b)
typedef long long ll;
//typedef __int64 LL;
const int inf = 0x3f3f3f3f;
const int N = 100010;
struct node{
int l, r;
int add, x;
}tr[26][N << 2];
char a[N];
char ans[N];
int n, m;
void pushup( int id, int rt )
{
tr[id][rt].x = tr[id][ls].x + tr[id][rs].x;
}
void down( int id, int rt )
{
if( tr[id][rt].add ) {
if( tr[id][rt].add == 1 ) {
tr[id][ls].x = tr[id][ls].r - tr[id][ls].l + 1;
tr[id][rs].x = tr[id][rs].r - tr[id][rs].l + 1;
}
else
tr[id][ls].x = tr[id][rs].x = 0;
tr[id][ls].add = tr[id][rs].add = tr[id][rt].add;
tr[id][rt].add = 0;
}
}
void build( int id, int l, int r, int rt )
{
tr[id][rt].l = l;
tr[id][rt].r = r;
tr[id][rt].add = 0;
if( l == r ) {
tr[id][rt].x = ( a[l] == 'a' + id );
return;
}
int mid = ( l + r ) >> 1;
build( id, lson );
build( id, rson );
pushup( id, rt );
}
int query( int id, int l, int r, int rt )
{
if( l <= tr[id][rt].l && tr[id][rt].r <= r ) {
return tr[id][rt].x;
}
down( id, rt );
int mid = ( tr[id][rt].l + tr[id][rt].r ) >> 1;
if( r <= mid )
return query( id, l, r, ls );
else if( l > mid )
return query( id, l, r, rs );
else
return query( id, lson ) + query( id, rson );
}
void update( int id, int l, int r, int rt, int val )
{
if( l <= tr[id][rt].l && tr[id][rt].r <= r ) {
if( val == 1 )
tr[id][rt].x = tr[id][rt].r - tr[id][rt].l + 1;
else
tr[id][rt].x = 0;
tr[id][rt].add = val;
return;
}
down( id, rt );
int mid = ( tr[id][rt].l + tr[id][rt].r ) >> 1;
if( r <= mid )
update( id, l, r, ls, val );
else if( l > mid )
update( id, l, r, rs, val );
else {
update( id, lson, val );
update( id, rson, val );
}
pushup( id, rt );
}
void get_ans( int id, int rt )
{
if( tr[id][rt].l == tr[id][rt].r ) {
if( tr[id][rt].x )
ans[ tr[id][rt].l ] = id + 'a';
return;
}
down( id, rt );
get_ans( id, ls );
get_ans( id, rs );
}
int main()
{
while( ~scanf("%d%d", &n, &m) ) {
scanf("%s", a+1);
for( int i = 0; i < 26; ++i ) {
build( i, 1, n, 1 );
}
for( int i = 1, l, r, op; i <= m; ++i ) {
scanf("%d%d%d", &l, &r, &op);
int tmp[30];
for( int j = 0; j < 26; ++j ) {
tmp[j] = query( j, l, r, 1 );
}
if( op == 1 ) {
for( int j = 0; j < 26; ++j ) {
update( j, l, r, 1, -1 );
}
int curl, curr, lastr = l-1;
for( int j = 0; j < 26; ++j ) {
if( !tmp[j] )
continue;
curl = lastr+1;
curr = lastr + tmp[j];
update( j, curl, curr, 1, 1 );
//printf("char: %c l: %d r: %d\n", j+'a', curl, curr);
lastr = curr;
}
}
else {
for( int j = 0; j < 26; ++j ) {
update( j, l, r, 1, -1 );
}
int curl, curr, lastr = l-1;
for( int j = 25; j >= 0; --j ) {
if( !tmp[j] )
continue;
curl = lastr+1;
curr = lastr+tmp[j];
update( j, curl, curr, 1, 1 );
//printf("char: %c l: %d r: %d\n", j+'a', curl, curr);
lastr = curr;
}
}
}
ans[n+1] = '\n';
for( int i = 0; i < 26; ++i ) {
get_ans( i, 1 );
}
printf("%s\n", ans+1);
}
return 0;
}