「joisc 2014 day1」有趣的家庭菜園
前置技能:樹狀陣列。
如果我們知道了目標序列,我們就可以構造乙個序列p,它的每乙個元素就是目標序列這一位置的元素在原序列的位置,那麼答案就是原位置序列[也就是]通過氣泡排序達到目標序列所需的交換次數目。而氣泡排序的交換次數就是p的逆序對的數量。
由於要滿足那兩個條件,那麼最後得到的序列一定是乙個單增,單減或是先單增,再單減。(不嚴格單增與單減,即可以相等)
故我們從大到小列舉ioi草,ioi草要麼位於之前放在之前的ioi草左邊,或者是右邊。
一種合法順序如下。(方框內寫的是放的順序)
然後每放一次,都用樹狀陣列求出放在左邊的增加的逆序對,再求出放在右邊的時候增加的逆序對。放在哪邊增加的逆序對少就放在哪邊。(這個貪心是正確的就是因為比他大的ioi草要麼都放在它的左邊,要麼都放在它的右邊)
當我們列舉到一堆高度相等的ioi草時怎麼放呢?首先對於乙個ioi草,記它放入序列左邊時增加的逆序對為lcost個,放在序列右邊增加的逆序對為rcost個,那麼如果他在原序列中的相對位置越大,它的lcost就會越大,它的rcost就會越小。於是我們可以把lco
st≤r
cost
lcost \leq rcost
lcost≤
rcos
t的ioi草放在序列左邊,另一些放在右邊。不難發現lco
st≤r
cost
lcost\leq rcost
lcost≤
rcos
t的ioi草在原序列中的相對位置會小於lco
st>rc
ostlcost > rcost
lcos
t>rc
ost的ioi草。又我們可以讓這些ioi草互相之間產生的逆序對數量為0(當這些ioi草放置後他們在原序列中的相對位置與目標序列的相對位置相同)。這樣子放肯定是最優的。實現方法就是先算出各自他們的答案,再在樹狀陣列上更新。
ac**:
#include
#include
#include
#define m 300005
#define lowbit(x) x&-x
using
namespace std;
int h[m]
;int n;
bool
cmp(
int x,
int y)
struct bin
void
add(
int x)
}int
sum(
int x)
return res;
}}b;
int id[m]
;int stk[m]
;void
solve()
else
}printf
("%lld\n"
,ans);}
intmain()
JOISC 2015 Day 1 卡片占卜
點此看題 可以把原來的陣列表示成差分陣列,那麼只有a 1 a b 1.a 1,a b 1.a 1,a b 1.這四個位置有值,我們要把所有值給消去。把操作理解為建邊,那麼找出兩個關鍵點的最短路就是消去這兩個關鍵點,那麼我們消去兩對關鍵點就可以了,有乙個特殊情況就是乙個點和n 1 n 1n 1相連,那...
JOISC 2020 Day1 建築裝飾 4
loj 考慮設 f 表示到了第 i 個位置,用了 j 個a,k 個b的可行性,打表發現對於 i,j 的 k 是連續的,所以考慮記錄 l 表示前 i 個位置用了 j 個a最少用多少個b,r 同理.最後輸出方案的時候一步一步的倒推即可.include include include include in...
NOIP2014day1 聯合權值
首先這是棵樹,那麼任意兩點間就只有一條路徑。要想值為2,那麼就需要兩個點連到同乙個點,即與同乙個點直接相連 那麼我們就可以列舉中間的點,然後遍歷它所有與其相連的點。另外總和權值可以這麼算 假如有兩個點 2ab a b 2 a2 b2 2ab a b 2 a 2 b 2 2ab a b 2 a2 b2...