TJ 2 P4505
破题 & 承题
题面有毒,用正常人的语言翻译一下,就是说:
在给出的数中选一定量的数。对于这之中的一个数
起讲 & 入手
很显然,考虑贪心。
用优先队列来记录,用变量
读入下一个数前,先判定
于是核心代码如下:
if (reader>>n, n == 1){//reader是快读
printf("%d\n", reader?0:-1);
continue;
}
while (!corder.empty())corder.pop();//由于多组数据,于是需要清空优先队列
counter = reader - 1, otp = 1;//第一个数肯定要选
for (i = 2;i <= n;i ++){//i 定义在外面,方便判定无解后把数列读完
if (counter)counter --;
else {
if (corder.empty() || corder.top() < 2){//已空或者最大的也不够再移动指针
otp = -1;//otp 即 output
break;
}else {
otp ++, counter = corder.top() - 2;//修改 counter,答案加一
corder.pop();
}
}
corder.push(reader);//把下一个数推入
}
while (i <= n){//这是用来在无解后读完剩余数字的
reader.scan();
i ++;
}
printf("%d\n", otp);
起股 & 中股 & 后股
完整代码如下:
#include <queue>
#include <cstdio>
using std::priority_queue;
const int N = 2e6 + 7;
int n, T, counter, otp;
struct readers{//快读
char now;
bool state;
inline int scan(){
register int ans = 0;
state = false;
while (now = getchar(), 48 > now || now > 57)state = now == 45;
while (48 <= now && now <= 57){
ans = (ans<<1) + (ans<<3) + (now^48);
now = getchar();
}
if (state)ans = -ans;
return ans;
}
readers operator >>(int &goal){
goal = scan();
return *this;
}
operator int(){return scan();}
}reader;
priority_queue<int> corder;
//%: define FLE "logic"
int main(){
// freopen(FLE ".in", "r", stdin);
// freopen(FLE ".out", "w", stdout);
register int i;
reader>>T;
while (T --){
if (reader>>n, n == 1){
printf(/*"n = 1, "*/ "%d\n", reader?0:-1);
continue;
}
// printf(">>>n is %d<<<\n", n);
while (!corder.empty())corder.pop();
counter = reader - 1, otp = 1;
for (i = 2;i <= n;i ++){
if (counter)counter --;
else {
if (corder.empty() || corder.top() < 2){
otp = -1;
// printf(">>>break with i = %d<<<\n", i);
break;
}else {
otp ++, counter = corder.top() - 2;
corder.pop();
}
}
// printf(">>>end with i = %d<<<\n", i);
corder.push(reader);
}
while (i <= n){
reader.scan();
i ++;
}
printf("%d\n", otp);
}
return 0;
}
束股
这道题难度实际上不大,主要是题面有毒。
顺带一提,被 T 的考虑开快读,因为: