1、HDU 5821 Ball
假设有4个红球,初始时从左到右标为1,2,3,4。那么肯定存在一种方案,使得最后结束时红球的顺序没有改变,也是1,2,3,4。那么就可以把同色球都写成若干个不同色球了
所以现在共有n个颜色互异的球。按照最终情况标上1,2,。。,n的序号,那么贪心的来每次操作就是把一个区间排序就行了
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <queue>
#include <vector>
#include <stack>
#include <map>
#include <cmath>
#include <cctype>
#include <bitset>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef unsigned int uint;
typedef pair<int, int> Pair;
const ull mod = 1e9 + 7;
const int INF = 0x7fffffff;
const int maxn = 1e3 + 10;
int a[maxn];
int n, m;
int vis[maxn];
int main()
{
#ifdef __AiR_H
freopen("in.txt", "r", stdin);
#endif // __AiR_H
int t;
scanf("%d", &t);
while (t--) {
queue<int> Q[maxn];
scanf("%d %d", &n, &m);
memset(vis, 0, sizeof(vis));
bool flag = true;
for (int i = 1; i <= n; ++i) {
scanf("%d", &a[i]);
++vis[a[i]];
}
int b;
for (int i = 1; i <= n; ++i) {
scanf("%d", &b);
--vis[b];
Q[b].push(i);
}
for (int i = 1; i <= n; ++i) {
if (vis[i] != 0) {
flag = false;
break;
}
}
if (flag) {
for (int i = 1; i <= n; ++i) {
int t = a[i];
a[i] = Q[t].front();
Q[t].pop();
}
}
int l, r;
while (m--) {
scanf("%d %d", &l, &r);
if (flag) {
sort(a+l, a+r+1);
}
}
for (int i = 1; i <= n; ++i) {
if (a[i] != i) {
flag = false;
break;
}
}
if (flag) {
printf("Yes\n");
} else {
printf("No\n");
}
}
return 0;
}
2、XTU 1252 Defense Tower
解题思路:
按照攻击力从大到小进行破坏,所以当我们破坏某个防御塔的时候,攻击力小于它的防御塔必然没有被破坏
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <queue>
#include <vector>
#include <stack>
#include <map>
#include <cmath>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef unsigned int uint;
const int mod = 1e9 + 7;
const int INF = 0x7fffffff;
const int maxn = 1e5 + 10;
int n;
int power[maxn];
int main()
{
while (scanf("%d", &n) != EOF) {
for (int i = 1; i <= n; ++i) {
scanf("%d", &power[i]);
}
int ans = 0;
int a, b;
for (int i = 0; i < n-1; ++i) {
scanf("%d%d", &a, &b);
ans += min(power[a], power[b]);
}
printf("%d\n", ans);
}
return 0;
}
3、Codeforces 527D Clique Problem
参考:http://www.cnblogs.com/qzqzgfy/p/5627186.html
题意:
给出一些点的 xi 和 wi,当 |xi − xj| ≥ wi+wj 的时候,两点间存在一条边,找出一个最大的集合,集合中的点两两之间存在边
解题思路:
若 |xi - xj| ≥ wi + wj
可能有 xi - xj ≥ wi + wj 或 xj - xi ≥ wi + wj 两种情况
那么有 wj + xj ≤ xi - wi 或 wi + xi ≤ xj - wj
所以将这些点按照 w + x 排序后,从最小的到最大的贪心连边,就可以保证这些点两两之间存在边
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <queue>
#include <vector>
#include <stack>
#include <map>
#include <set>
#include <cmath>
#include <cctype>
#include <bitset>
#include <ctime>
using namespace std;
#define REP(i, n) for (int i = 0; i < (n); ++i)
#define lson low, mid, _id<<1
#define rson mid+1, high, _id<<1|1
typedef long long ll;
typedef unsigned long long ull;
typedef unsigned int uint;
typedef pair<int, int> Pair;
const ull mod = 1e9 + 7;
const int INF = 0x7fffffff;
const int maxn = 2e5 + 10;
struct Node {
int x, w;
bool operator < (Node a) {
return x+w < a.x+a.w;
}
};
int n;
Node node[maxn];
int main()
{
#ifdef __AiR_H
freopen("in.txt", "r", stdin);
#endif // __AiR_H
scanf("%d", &n);
for (int i = 0; i < n; ++i) {
scanf("%d %d", &node[i].x, &node[i].w);
}
sort(node, node+n);
int t = node[0].w + node[0].x, ans = 0;
for (int i = 1; i < n; ++i) {
if (t <= node[i].x - node[i].w) {
++ans;
t = node[i].x + node[i].w;
}
}
printf("%d\n", ans+1);
return 0;
}
4、Codeforces 383A Milking cows
解题思路:
先从右到左给面朝左的奶牛挤奶,然后再从左到右给面朝右的奶牛挤奶
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <queue>
#include <vector>
#include <stack>
#include <map>
#include <set>
#include <cmath>
#include <cctype>
#include <bitset>
#include <ctime>
using namespace std;
#define REP(i, n) for (int i = 0; i < (n); ++i)
#define lson low, mid, _id<<1
#define rson mid+1, high, _id<<1|1
typedef long long ll;
typedef unsigned long long ull;
typedef unsigned int uint;
typedef pair<int, int> Pair;
const ll mod = 1e9 + 7;
const int INF = 0x7fffffff;
const int maxn = 2e5 + 10;
ll n;
ll a[maxn], sum[maxn];
int main()
{
#ifdef __AiR_H
freopen("in.txt", "r", stdin);
#endif // __AiR_H
scanf("%I64d", &n);
for (ll i = 1; i <= n; ++i) {
scanf("%I64d", &a[i]);
sum[i] = sum[i-1] + a[i];
}
ll ans = 0;
for (ll i = n; i >= 1; --i) {
if (a[i] == 0) {
ans += sum[i];
}
}
printf("%I64d\n", ans);
return 0;
}
5、2016-2017 ACM-ICPC, NEERC, Southern Subregional Contest (Online Mirror, ACM-ICPC Rules, Teams Preferred) A Toda 2
解题思路:
按情况每次减 3 或者减 2
例如 1 4 4 4 这种情况就需要减 3
在队友代码基础上 xjb 改了改,感觉压行还好吧...
#include<cstdio>
#include<algorithm>
#include <queue>
using namespace std;
const int INF = 0x7fffffff;
int s[10005][10005];
struct node
{
int id;
int num;
bool operator < (const node &b)const
{
return num < b.num;
}
}a[105];
int Min = INF, sum = 0;
priority_queue<node> Queue;
int main()
{
int n,i,k,j;
scanf("%d", &n);
for(i = 0; i < n; i++)
{
scanf("%d", &a[i].num);
sum += a[i].num;
if (a[i].num < Min) {
Min = a[i].num;
}
a[i].id = i;
Queue.push(a[i]);
}
k = 0;
while(1)
{
node f1 = Queue.top(), f2, f3;
if (f1.num == Min) {
break;
}
if (Queue.size() >= 4 && (sum - Min * Queue.size()) % 2 == 1) {
Queue.pop(), f2 = Queue.top(), Queue.pop(), f3 = Queue.top(), Queue.pop();
if (f1.num > 0) --f1.num, --sum;
if (f2.num > 0) --f2.num, --sum;
if (f3.num > 0) --f3.num, --sum;
if (Min > f1.num) Min = f1.num;
if (Min > f2.num) Min = f2.num;
if (Min > f3.num) Min = f3.num;
Queue.push(f1), Queue.push(f2), Queue.push(f3);
for(i = 0; i < n; i++) s[k][i] = ((i == f1.id || i == f2.id || i == f3.id) ? 1 : 0);
} else {
Queue.pop(), f2 = Queue.top(), Queue.pop();
if (f1.num > 0) --f1.num, --sum;
if (f2.num > 0) --f2.num, --sum;
if (Min > f1.num) Min = f1.num;
if (Min > f2.num) Min = f2.num;
Queue.push(f1), Queue.push(f2);
for(i = 0; i < n; i++) s[k][i] = ((i == f1.id || i == f2.id) ? 1 : 0);
}
k++;
}
printf("%d\n", Min);
printf("%d\n", k);
for(i = 0; i < k; i++)
{
for(j = 0; j < n; j++)
printf("%d", s[i][j]);
printf("\n");
}
return 0;
}