分析:暴力分挺多,也挺好想的,個人感覺兩個特殊性質沒什麼卵用.
對於k=1,n ≤ 1024的情況,從後往前貪心地分,如果能和上一組分在一起就分在一起,否則就再開一組,這樣可以保證字典序最小.ai ≤ 2就看前面有沒有2.有就不能分在一組.n ≤ 131072就不能再這樣二重迴圈列舉了,因為兩個數的和頂多只有262114 = 512^2,從1列舉到512,看看它的平方有沒有被占用就可以了,就把問題從序列上轉化到了值域上.
對於k=2,其實做法和k=1沒什麼兩樣,只是每一組可以分成兩個對立的小組,非常像noip2010關押罪犯,加乙個並查集就好了.用乙個vector存每個值的兔子的位置,判斷一下有沒有衝突就好了.
暴力+正解:
#include #include#include
#include
#include
#include
using
namespace
std;
const
int maxn = 131072
;vector
e[maxn * 2 + 10
];int n, k, a[150000], ans[150000], cnt, fa[300010], vis[300010
], t;
bool flag = true
;bool check2(int
x)
return
true;}
int find(int
x)bool check(int x, int
y)void
solve1()}}
printf(
"%d\n
", cnt + 1
);
for (int i = cnt; i >= 1; i--)
printf(
"%d
", ans[i]);
printf("\n
");}
else
if(flag)
if (a[i] == 2
) flag2 = 1
; }
printf(
"%d\n
", cnt + 1
);
for (int i = cnt; i >= 1; i--)
printf(
"%d
", ans[i]);
printf("\n
");}
else
vis[a[i]] = 1
; }
printf(
"%d\n
", cnt + 1
);
for (int i = cnt; i >= 1; i--)
printf(
"%d
", ans[i]);
printf("\n
");}
}void hebing(int x, int
y)bool check3(int
x) }
}return
true;}
void
solve2()
if (a[i] == 2
) flag2++;
}printf(
"%d\n
", cnt + 1
);
for (int i = cnt; i >= 1; i--)
printf(
"%d
", ans[i]);
printf("\n
");}
else
if (n <= 1024
)
else}}
}printf(
"%d\n
", cnt + 1
);
for (int i = cnt; i >= 1; i--)
printf(
"%d
", ans[i]);
printf("\n
");}
else
if (vis[a[i]] !=t)
e[a[i]].push_back(i);
}printf(
"%d\n
", cnt + 1
);
for (int i = cnt; i >= 1; i--)
printf(
"%d
", ans[i]);
printf("\n
");}
}int
main()
if (k == 1
) solve1();
if (k == 2
) solve2();
return0;
}
noip模擬賽 罪犯分組
分析 看了題後沒別的思路,感覺就是dp,普通dp的話狀態和方程實在是不好設計,觀察資料,發現n非常小,暗示了這道題要用狀壓dp來做.先列舉每個集合,再用o n 2 的暴力看這個集合內有多少個衝突,如果衝突數量不大於k,那麼就可以分成1個集合了,否則一定要分成多個集合,那麼列舉它的子集j,狀態轉移方程...
洛谷noip模擬賽 分組
小 c 在了解了她所需要的資訊之後,讓兔子們調整到了恰當的位置。小 c 準備給兔子 們分成若干個小組來喂恰當的胡蘿蔔給兔子們吃。此時,nn 只兔子按一定順序排成一排,第 ii 只兔子的顏色是 a iai 由於順序已經是被 調整好了的,所以每個小組都應當是序列上連續的一段。在分組前,小 c 發現了乙個...
NOIP 模擬試題之 分組
問題描述 mr he打算把自己棋下的 n 個選手分成若干組。每個選手都提出自己的要求,那就是第 i 個選手要求自己所屬的組的人數大等於a i 人。在滿足所有選手的要求的前提下,mr he打算最大化組的總數,請你來幫助他!注意,分組時每個選手屬於且僅屬於一組。輸入格式 第一行乙個整數 n,表示人數。以...