C
大意就是给定一个数列,每次使一个数变成0,求每次变化以后不包括零的子数列的和的最大值是多少。
可以逆推。
这让我想到了以前的一道题
http://blog.youkuaiyun.com/vectorxj/article/details/51477089 就是将问题反过来求并查集。
这道题其实道理也类似,问题就转化成每次加入一个数,求不包括零的子数列的和的最大值是多少。就需要用两个数组
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <queue>
using namespace std;
typedef long long ll;
inline char get(void) {
static char buf[100000], *p1 = buf, *p2 = buf;
if (p1 == p2) {
p2 = (p1 = buf) + fread(buf, 1, 100000, stdin);
if (p1 == p2) return EOF;
}
return *p1++;
}
template<typename T>
inline int read(T &x) {
static char c; x = 0;
for (c = get(); c < '0' || c > '9'; c = get());
for (; c >= '0' && c <= '9'; x = x * 10 + c - '0', c = get());
return x;
}
inline ll Max(ll a, ll b) {
return a > b ? a : b;
}
const int N = 100010, INF = 1 << 30;
int q[N], l[N], r[N];
ll num[N], ans[N];
int n, x, y, p;
int main(void) {
read(n);
for (int i = 1; i <= n; i++) {
read(num[i]); num[i] += num[i - 1];
l[i] = r[i] = i;
}
for (int i = 0; i < n; i++) read(q[i]);
for (int i = n - 1; i; i--) {
p = q[i]; x = l[p - 1];
if (l[p + 1] == p) y = r[p + 1];
else y = p;
ans[i] = Max(ans[i + 1], num[y] - num[x]);
l[y] = l[p] = x; r[x + 1] = y;
}
for (int i = 1; i <= n; i++) printf("%I64d\n", ans[i]);
return 0;
}
D
两种变换:
1.Take any integer xi and multiply it by two, i.e. replace xi with 2·xi.
2.Take any integer xi, multiply it by two and add one, i.e. replace xi with 2·xi + 1.
问一个集合能否能由另一个集合变化而来,且该集合的元素最大值最小。
感觉很简单吧。贪心加搜索搞一搞就好了,每次找到最大值取出不断判断除以二之后的值是否属于集合即可。原理很好想。
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <set>
using namespace std;
inline char get(void) {
static char buf[100000], *p1 = buf, *p2 = buf;
if (p1 == p2) {
p2 = (p1 = buf) + fread(buf, 1, 100000, stdin);
if (p1 == p2) return EOF;
}
return *p1++;
}
template<typename T>
inline int read(T &x) {
static char c; x = 0;
for (c = get(); c < '0' || c > '9'; c = get());
for (; c >= '0' && c <= '9'; x = x * 10 + c - '0', c = get());
return x;
}
const int N = 50010;
struct cmp {
bool operator ()(int a, int b) {
return a > b;
}
};
typedef set<int, cmp> ms;
ms S;
int n, x, a[N];
inline void Modify(int x) {
S.erase(S.find(x)); S.insert(x >> 1);
}
bool check(int x) {
if (!(x >> 1)) return false;
if (S.find(x >> 1) != S.end()) {
bool b = check(x >> 1);
if (b) Modify(x);
return b;
}
Modify(x);
return true;
}
int main(void) {
read(n);
for (int i = 1; i <= n; i++) S.insert(read(a[i]));
while (1) {
x = *S.begin();
if (!check(x)) break;
}
for (ms::iterator i = S.begin(); i != S.end(); i++)
printf("%d ", *i);
}