CDQ分治 HNOI2010 城市建設

2022-04-30 20:24:13 字數 1510 閱讀 2103

題目鏈結

線段樹分治+lct只有80

然後就有了cdq分治的做法

把不可能在生成樹里的扔到後面

把一定在生成樹里的扔到並查集裡存起來

分治到l=r,修改邊權,跑個kruskal就行了

由於要支援撤銷,並查集要按秩合併

#include"cstdio"

#include"cstring"

#include"iostream"

#include"algorithm"

using namespace std;

const int maxn=2e4+5;

const int maxm=5e4+5;

const int inf=1e9;

int n,m,q,t,ct,p;

int f[maxn],mxdp[maxn];

long long sum;

long long ans[maxm];

bool vis[maxm];

int v[maxm];

struct rpga[maxm],st[maxm];

struct vxw[maxm];

struct fxstk[maxm];

int read()

,++mxdp[fb];

else stk[++ct]=(fx);

f[fa]=fb;

}long long calc(int d,int t2)

}sort(a+1,a+t+1,cmp1);

long long s=0;

for(int i=1;i<=t;++i)while(ct>t2)return sum+s;

}void c(int t2)

return;

}void d(int t2)

}sort(a+1,a+t+1,cmp2);

while(t&&a[t].kd) --t;

while(ct>t2)return;

}void red(int t2)

return;

}void rec(int t1)

t=t1;

return;

}void cdq(int l,int r)

int ctp=t,cmd=ct,mid=l+r>>1;

for(int i=1;i<=t;++i) vis[a[i].id]=0;

for(int i=l;i<=r;++i) vis[w[i].id]=1;

c(cmd),d(cmd);

for(int i=t+1;i<=ctp;++i) if(a[i].kd==1) un(find(a[i].ls),find(a[i].nx));

for(int i=1;i<=t;++i) a[i].ln=st[a[i].id].ln;

cdq(l,mid),cdq(mid+1,r);

rec(ctp);red(cmd);

return;

}int main()

hnoi2010 彈飛綿羊

題目描述很明確,現在的目標是均攤兩個操作的複雜度 現在我們已知有兩種方法 1.每次用o 1 的時間修改k值,用o n 的時間直接模擬回答詢問 2.每次修改了k值後用o n 的時間更新所有答案,o 1 時間回答 均攤這兩種操作,可以這樣做 由於只可以從前往後跳,所以可以把跳躍路徑壓縮,更新時把壓縮的部...

HNOI 2010 彈飛綿羊

要求維護乙個 n 個節點的森林,實現 m個詢問,其中包括 n 200,000m 100,000 動態樹的入門題。只需要實現ac cess 操作以及維護子樹大小si ze即可。其實我做這道題是為了找找寫動態樹的感覺,發現了不少要注意的細節。總結地說,越是基本的函式就越不能打錯,不然就要花好多的時間去查...

HNOI2010彈飛綿羊

話說我是冒著巨大的風險a這道題的 xc說不讓上其他oj 這題其實很簡單,每個點如果他能往後跳,那就只能跳到唯一的乙個,這顯然是跟森林,用lct就好,維護下size。突然變短 include include define fo i,a,b for int i a i b i define lc c x...