題目鏈結
線段樹分治+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...