A. Professor GukiZ’s Robot
题意
robot可以走八个方向。给出起点坐标和终点坐标,问最少要走几次。
思路
最优当然是尽可能的斜着走喽。
code
cout << max(abs(x_1 - x_2), abs(y_1 - y_2)) << endl;
B. Grandfather Dovlet’s calculator
题意
max用计算器从数字a按倒数字b,问计算器显示了多少segments
思路
暴力循环a~b,然后数位分离并累加。
code
for (int s = x; s <= y; s++) {
int tmp = s;
while (tmp) {
ans += 1LL * a[tmp % 10];
tmp /= 10;
}
}
C. Pearls in a Row
题意
一个数组中连续的序列称为一个段,一个段中有至少两个数字相同称为好的段,问给出的数组最多能被分成多少个段,要求不重不漏。
思路
贪心,从左往右找,一旦发现数字重复出现过立即分一个段出来,直到分完。注意要让最后一个段包含后面所有的数字。
code
#include<bits/stdc++.h>
using namespace std;
int n, cnt, l;
int a[300000 + 5];
map<int, int > m;
vector<pair<int, int> > v;
int main () {
scanf ("%d", &n);
l = 1;
for (int i=1; i<=n; i++) {
scanf ("%d", &a[i]);
if (m[a[i]] == 0) {
m[a[i]] = i;
} else {
cnt++;
v.push_back(make_pair(l, i));
l = i+1;
m.clear();
}
}
if (cnt != 0) {
printf ("%d\n",cnt);
for (int i=0; i<cnt-1; i++) {
printf ("%d %d\n", v[i].first, v[i].second);
}
printf ("%d %d\n", v[cnt-1].first, n);
} else printf ("-1\n");
return 0;
}
D. Professor GukiZ and Two Arrays
题意
对于a,b两个数组,最多交换两个数字使得他们数组元素的和的差的绝对值最小。
思路
分三种情况
交换0次
直接计算差值。交换1词
枚举两个数组交换的值。交换2次
对b数组找出所有交换两次的方案并排序。
枚举a数组要换的两个数
在b数组中二分找最优的解
应为是绝对值,所以该解的前后也有可能更优
code
#include <bits/stdc++.h>
using namespace std;
const int INF = 999999999;
const int MAXN = 2000 + 5;
int n, m;
long long a[MAXN], b[MAXN];
long long sum_a, sum_b;
long long val_zero = INF;
void solve_zero () {
val_zero = abs(sum_a - sum_b);
}
long long val_one = INF;
int ans_one_a = -1, ans_one_b = -1;
void solve_one () {
val_one = abs(sum_a - sum_b);
for (int i=1; i<=n; i++) {
for (int j=1; j<=m; j++) {
long long tmp_a = sum_a - a[i] + b[j];
long long tmp_b = sum_b - b[j] + a[i];
if (abs(tmp_a - tmp_b) < val_one) {
val_one = abs(tmp_a - tmp_b);
ans_one_a = i;
ans_one_b = j;
}
}
}
}
struct Node {
long long val;
int pos_i, pos_j;
Node(){}
Node (long long va, int pi, int pj) {
val = va;
pos_i = pi;
pos_j = pj;
}
}c[MAXN * MAXN];
bool cmp (Node a, Node b) {
return a.val < b.val;
}
int k=0;
long long val_two = INF;
pair<int, int> ans_two_a = make_pair(-1, -1);
pair<int, int> ans_two_b = make_pair(-1, -1);
void solve_two () {
val_two = abs(sum_a - sum_b);
for (int i=1; i<=m; i++) {
for (int j=i+1; j<=m; j++) {
c[k++] = Node(b[i] + b[j], i, j);
}
}
sort(c, c+k, cmp);
for (int i=1; i<=n; i++) {
for (int j=i+1; j<=n; j++) {
long long aa = a[i] + a[j];
Node bb = Node ((sum_b - sum_a + 2 * aa) / 2, i, j);
int p = lower_bound(c, c+k, bb, cmp) - c;
if (p >= 0 && p < k) {
if (abs(sum_a - 2 * aa - sum_b + 2 * c[p].val) < val_two) {
val_two = abs(sum_a - 2 * aa - sum_b + 2 * c[p].val);
ans_two_a = make_pair(i, j);
ans_two_b = make_pair(c[p].pos_i, c[p].pos_j);
}
}
if (p > 0) {
if (abs(sum_a - 2 * aa - sum_b + 2 * c[p-1].val) < val_two) {
val_two = abs(sum_a - 2 * aa - sum_b + 2 * c[p-1].val);
ans_two_a = make_pair(i, j);
ans_two_b = make_pair(c[p-1].pos_i, c[p-1].pos_j);
}
}
if (p < k-1) {
if (abs(sum_a - 2 * aa - sum_b + 2 * c[p+1].val) < val_two) {
val_two = abs(sum_a - 2 * aa - sum_b + 2 * c[p+1].val);
ans_two_a = make_pair(i, j);
ans_two_b = make_pair(c[p+1].pos_i, c[p+1].pos_j);
}
}
}
}
}
int main () {
scanf ("%d", &n);
for (int i=1; i<=n; i++) {
scanf ("%I64d", &a[i]);
sum_a += a[i];
}
scanf ("%d", &m);
for (int i=1; i<=m; i++) {
scanf ("%I64d", &b[i]);
sum_b += b[i];
}
solve_zero();
solve_one ();
solve_two ();
if (val_zero <= val_one && val_zero <= val_two) {
printf ("%I64d\n0\n", val_zero);
} else if (val_one <= val_zero && val_one <= val_two) {
printf("%I64d\n1\n", val_one);
printf("%d %d\n", ans_one_a, ans_one_b);
} else if (val_two <= val_zero && val_two <= val_one) {
printf("%I64d\n2\n", val_two);
printf("%d %d\n", ans_two_a.first, ans_two_b.first);
printf("%d %d\n", ans_two_a.second, ans_two_b.second);
}
return 0;
}
Update in 23:19 2016-1-28
E. New Year Tree
题意
Resha 有棵树,树的每个节点都有一种颜色,现在给出两种操作
- 把某个子树的所有节点的颜色修改为s
- 查询某个节点所在子树的颜色种数
思路
这题看起来难,实则不然。
对于一棵树妖对其子树操作,我们很容易想到他的dfs序列。因为在dfs序列中,一棵子树对应着序列的一个子串。(我们其实并不需要找出该序列,只需知道每个节点的子树在序列的起始和终点位置)
由此问题转换为对一个序列的区间查询和修改操作。可以用线段树很好的解决。而颜色的问题,我们可以用long long
保存信息,每个二进制位表示是否有改该颜色。
于是,问题就解决了,码代码时多注意下就行。
code
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 400000 + 5;
int n, m;
long long c[MAXN];
vector<int > v[MAXN];
struct Node {
int l, r;
Node() {}
Node (int _l, int _r) {
l = _l;
r = _r;
}
}tc[MAXN];
long long bc[MAXN];
int dfs_counter = 1;
void dfs(int t, int fa) {
tc[t].l = dfs_counter;
for (int i=0; i<v[t].size(); i++) {
if (v[t][i] == fa) continue;
dfs(v[t][i], t);
}
tc[t].r = dfs_counter;
bc[dfs_counter] = c[t];
dfs_counter++;
}
long long sg[MAXN * 4];
long long lz[MAXN * 4];
struct Sgment {
Sgment() {
memset (sg, 0, sizeof sg);
memset (lz, -1, sizeof lz);
}
void push_up(int lr) {
sg[lr] = sg[lr<<1] | sg[lr<<1|1];
}
void push_down (int lr) {
if (lz[lr] != -1) {
lz[lr<<1] = lz[lr];
lz[lr<<1|1] = lz[lr];
sg[lr<<1] = lz[lr];
sg[lr<<1|1] = lz[lr];
lz[lr] = -1;
}
}
void create(int l, int r, int lr) {
if (l == r) {
sg[lr] = 1LL << bc[l];
return ;
}
int m = (l + r) / 2;
create (l, m, lr<<1);
create (m+1, r, lr<<1|1);
push_up (lr);
}
void update (int l, int r, int lr, int L, int R, long long s) {
if (l >= L && r <= R) {
sg[lr] = s;
lz[lr] = s;
return ;
}
push_down (lr);
int m = (l + r) / 2;
if (m >= L) update(l, m, lr<<1, L, R, s);
if (m < R) update(m+1, r, lr<<1|1, L, R, s);
push_up (lr);
}
long long query (int l, int r, int lr, int L, int R) {
if (l >= L && r <= R) {
return sg[lr];
}
push_down (lr);
long long res = 0;
int m = (l + r) / 2;
if (m >= L) res |= query (l, m, lr<<1, L, R);
if (m < R) res |= query (m+1, r, lr<<1|1, L, R);
return res;
}
};
int main () {
scanf ("%d %d", &n, &m);
for (int i=1; i<=n; i++) {
scanf ("%I64d", &c[i]);
}
int tmpa, tmpb;
for (int i=1; i<n; i++) {
scanf ("%d %d", &tmpa, &tmpb);
v[tmpa].push_back(tmpb);
v[tmpb].push_back(tmpa);
}
dfs(1, -1);
Sgment sg;
sg.create(1, n, 1);
int op, a, b;
for (int s=0; s<m; s++) {
scanf ("%d", &op);// cout << "op " << op << endl;
if (op == 1) {
scanf ("%d %d", &a, &b);
sg.update(1, n, 1, tc[a].l, tc[a].r, 1LL<<b);
} else {
scanf ("%d", &a);
long long ans = sg.query(1, n, 1, tc[a].l, tc[a].r);
// printf ("ans = %d\n",ans);
int cnt = 0;
for(int i=1; i<=60; i++) {
if ((ans & (1LL << i)) != 0) cnt++;
}
printf ("%d\n", cnt);
}
}
return 0;
}