洛谷 P3201 HNOI2009 夢幻布丁

2022-05-31 14:51:12 字數 1814 閱讀 4153

祭我ac的第十道紫題。

聽了一下午的

才調出來。

洛谷傳送門

給乙個序列a,有兩種操作——

1 x y將序列中所有x全部變成y

2查詢當前序列有多少段。

\(1\le n,m\le 10^5,1\le a_i,x,y\le 10^6\)。

考慮每修改乙個位置帶來的貢獻(亦或者說是影響?)。我們每將乙個\(a_i=x\)修改為了\(y\),那麼如果\(a_ =y\)或\(a_=y\)都會使段數\(+1\)。

但是這樣雖然簡化的操作\(2\),但是\(1\)還是需要\(o(n)\)的時間來維護。

但是如果我們修改顏色時,將數量少的那一種顏色修改為數量多的那一種,這樣修改次數就大大減少了。這種合併方案屬於啟發式合併

至於用什麼方式來合併。思來思去,還是用鍊錶解決最優。(當然什麼set,vector,線段樹合併都行)。

設煉表的值為\(f_i\),大小為\(size_i\),起點為\(head_i\),指標為\(next_i\)。

開始時,先將同一種顏色放到乙個鍊錶中,並計算原序列有多少段。

讀入\(x,y\)並比較鍊錶大小(注意交換的是\(f_x,f_y\),相當於交換了兩個鍊錶)。

統計貢獻之後再修改小煉表的顏色,把小煉表塞到打鍊錶的前面,更新大煉表的\(size,head\)。

清空小煉表的\(head,size\)。

#include#include#include#include#include#include#include#include#include#include#define il inline

#define re register

#define ll long long

#define ull unsigned long long

#ifdef th

#define debug printf("now is %d\n",__line__);

#else

#define debug

#endif

using namespace std;

templateinline void read(t&x)

x*=fu;

}inline int read()

return x*fu;

}int g[55];

templateinline void write(t x)

while(x);

for(int i=g;i>=1;--i)putchar('0'+g[i]);putchar('\n');

}#define n 100010

int n,m;

int a[n];

int ans;

int f[n*10],sze[n*10];

int head[n*10],nxt[n*10];

int main()

int op,x,y;

while(m--)

int j=0;

for(int i=head[x];i;i=nxt[i]) a[j=i]=y;

if(head[x]) nxt[j]=head[y],head[y]=head[x];

sze[y]+=sze[x];

sze[x]=0;

head[x]=0;

} else write(ans);

// for(int i=1;i<=n;i++) cout《注意特判\(x=y\)。

這個合併我實在是不會用vector,vector貌似不能\(o(1)\)合併……

洛谷 P3199 HNOI2009 最小圈

如果你能提供題面或者題意簡述,請直接在討論區發帖,感謝你的貢獻。對於一張有向圖,要你求圖中最小圈的平均值最小是多少,即若乙個圈經過k個節點,那麼乙個圈的平均值為圈上k條邊權的和除以k,現要求其中的最小值 輸入格式 第一行2個正整數,分別為n和m 以下m行,每行3個數,表示邊連線的資訊,輸出格式 一行...

洛谷 P3197 HNOI2008 越獄

來來來,日常水一篇 滑稽 監獄有連續編號為1 n的n個房間,每個房間關押乙個犯人,有m種宗教,每個犯人可能信仰其中一種。如果相鄰房間的犯人的宗教相同,就可能發生越獄,求有多少種狀態可能發生越獄 輸入格式 輸入兩個整數m,n.1 m 10 8,1 n 10 12 輸出格式 可能越獄的狀態數,模1000...

洛谷P3227 HNOI2013 切糕

題目大意 有乙個 n times m 的切糕,每乙個位置的高度可以在 1,k 之間,每個高度有乙個代價,要求四聯通的兩個格仔之間高度最多相差 d 問可行的最小代價。n,m,k,d leqslant 40 題解 網路流,不考慮相差為 d 的條件時,可以給每個位置建乙個點,源點連向高度為 1 的點容量為...