题解 P3566 【[POI2014]KLO-Bricks】
Last_Reincarnation · · 题解
快
这题见过好多遍了,也有好多人讲过, 自己认为很好写,然后一直没写,一些才发现原来有一点不好写(是我的代码能力太差了。。)
本题是一个练习代码能力和细节处理的好题
进入正题
1.贪心策略 :在保证相邻两个颜色不同时,先放多的,若一样多,则放与末尾颜色相同的。(正确性感性理解一下)
变量
int k, s, t, n, pre;//k为颜色数,s为第一个块颜色,t为最后一个块的颜色, n为总块数, pre为前一个快的颜色;
int ans[maxn];//记录答案;
bool flag;//代码中会解释用途;
struct Node{
int col, id;//这个结构体没啥用,可以用一个变量代替。。;
}a[maxn];
处理 一样多的 且 一样多的中有与末尾颜色一样的
struct note{
int now, w;//now颜色, w个数;
friend bool operator < (note a, note b){
if (a.w != b.w) return a.w < b.w; //大根堆应为小于号
if (a.now == t) return false;//t为末尾颜色
return true;
}
};
priority_queue<note>Q;
快读
int f_;
char ch_;
template <class T>
inline T read (T &x_){
x_ = 0, f_ = 1, ch_ = getchar();
while (ch_ > '9' || ch_ < '0'){if (ch_ == '-') f_ = -1; ch_ = getchar();}
while (ch_ >= '0' && ch_ <= '9') x_ = (x_ << 3) + (x_ << 1) + ch_ - 48, ch_ = getchar();
return x_*f_;
}
激动人心的时候(这么长时间,终于有代码啦)
#include <iostream>
#include <cstdio>
#include <queue>
using namespace std;
const int maxn = 1e6 + 10;
int k, s, t, n, cnt, pre;
int ans[maxn];
bool flag;
struct Node{
int col, id;
}a[maxn];
struct note{
int now, w;
friend bool operator < (note a, note b){
if (a.w != b.w) return a.w < b.w;
if (a.now == t) return false;
return true;
}
};
priority_queue<note>Q;
int f_;
char ch_;
template <class T>
inline T read (T &x_){
x_ = 0, f_ = 1, ch_ = getchar();
while (ch_ > '9' || ch_ < '0'){if (ch_ == '-') f_ = -1; ch_ = getchar();}
while (ch_ >= '0' && ch_ <= '9') x_ = (x_ << 3) + (x_ << 1) + ch_ - 48, ch_ = getchar();
return x_*f_;
}
int main(){
read(k);
read(s);
read(t);
for (register int i = 1;i <= k; ++i){
read(a[i].col);
a[i].id = i;
n += a[i].col;
if (a[i].id == s) a[i].col--;
if (a[i].id == t) a[i].col--;
if (a[i].col < 0) {printf("0"); return 0;}//题意要求,因为Bitie could have made a mistake,所以他会当块数没有他记忆中的多, 则跳出;
Q.push((note){i, a[i].col});
}
pre = s;//从第二个块开始,前一个块为s;
ans[1] = s;
ans[n] = t;
note top, tmp;
for (register int i = 2;i < n; ++i){
top = Q.top();
Q.pop();
flag = false;
if (top.now == pre){//这里是重点,若与前一个颜色相同则用tmp记录堆顶
flag = true;
tmp = top;
if (!Q.empty())
top = Q.top();//若第二堆顶有则放它,否则就会把两个一样的放在一起,然后跳出即可
else {
printf("0");
return 0;
}
Q.pop();
}
pre = ans[i] = top.now;
if (top.w > 1)
Q.push((note){top.now, top.w - 1});
if (flag)
Q.push(tmp);//若flag为一,则把原来堆顶放回去
}
if (ans[n-1] == ans[n]) {
printf("0");
return 0;
}
for (register int i = 1;i <= n; ++i){
if (i != n)
printf("%d ",ans[i]);
else printf("%d", ans[i]);
}
return 0;
}
最后记住pus("0")不行,因为它自带换行,因为忘记啦, 所以提交时60pt好几次
最后祝大家
日拱一卒,功不唐捐!!!