日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 人文社科 > 生活经验 >内容正文

生活经验

「2018山东一轮集训」 Tree

發(fā)布時(shí)間:2023/11/27 生活经验 43 豆豆
生活随笔 收集整理的這篇文章主要介紹了 「2018山东一轮集训」 Tree 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

?

?

??? 為什么出題人這么毒瘤啊??!!一個(gè)分塊還要帶log的題非要出成n<=2*1e5。。。。。。。

??? 為了卡過最后兩個(gè)點(diǎn)我做了無數(shù)常數(shù)優(yōu)化,包括但不限于:把所有線段樹改成 存差分的樹狀數(shù)組;把樹剖求LCA的極小的log優(yōu)化成rmq O(1)求LCA;根據(jù)測試情況手動調(diào)整siz的大小;

??? 但就是死也卡不過去,算了算了QWQ

?

(常規(guī)套路,先把1設(shè)成根建有根樹)

?

??? 這個(gè)題的主要思路就是 對節(jié)點(diǎn)的下標(biāo)分塊,設(shè) f[i][j] 為 第i個(gè)塊內(nèi)所有點(diǎn)到點(diǎn)j的距離和,然后看如何快速的動態(tài)維護(hù)這個(gè)玩意。。。。

??? 發(fā)現(xiàn)改動一條邊權(quán)的時(shí)候,只有兩個(gè)點(diǎn)分別位于這條邊兩側(cè)的時(shí)候才會對它們之間的dis有影響。

??? 我們設(shè)p為邊端點(diǎn)中更深的那個(gè),那么也就是一個(gè)在p子樹內(nèi),一個(gè)在子樹外的才有影響。。。。

??? 于是我們對每個(gè)塊開一個(gè)vector記錄一下這個(gè)塊內(nèi)的點(diǎn)的dfs序集合,排完序之后就可以之間O(log)的查詢某個(gè)塊在一棵子樹內(nèi)/外的點(diǎn)數(shù)了。。。

??? 因?yàn)閒[][]的第一維比較小,所以我們可以暴力枚舉第一維,然后對第二維進(jìn)行快速的修改。。。。。這時(shí)候發(fā)現(xiàn)第二維如果是存dfs序的話會更加方便(子樹內(nèi)可以直接進(jìn)行區(qū)間修改),所以就改成下標(biāo)代表dfs序啦。。。

???

??? 對于整塊整塊的一些點(diǎn)到某個(gè)點(diǎn)的距離,用上述方法就行啦。。。可以發(fā)現(xiàn)都是區(qū)間修改單點(diǎn)查詢,所以用差分的樹狀數(shù)組可以快(可能還不止)4倍常數(shù)哦。。。

???

??? 查詢零散的點(diǎn)對(i,j)之間的距離的話更加簡單。。可以動態(tài)維護(hù)dis[i]表示i到根的距離(發(fā)現(xiàn)也是區(qū)間修改單點(diǎn)查詢,所以可以類似上述整塊的方法處理),答案就是dis[i]+dis[j]-2*dis[LCA(i,j)]。。。

?

??? 可能說起來不是很多吧qwq?但是要寫一輩子啊QWQWQWQ。。。。

??? (我美好的下午就這么沒了QWQ)

??? 話說我把樹剖求LCA改成rmq之后反而更慢了QWQ,這是什么鬼啊。。。。

?

/*inside : b * dertaoutside : a * dertaall -> a * dertainside -> (b-a) * derta
*/
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<vector>
#include<iostream>
#define ll long long
using namespace std;
#define pb push_back
const int maxn=200003,N=205;inline int read(){int x=0; char ch=getchar();for(;!isdigit(ch);ch=getchar());for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0';return x;
}void W(ll x){ if(x>=10) W(x/10); putchar(x%10+'0');}int n,m,T,dep[maxn],siz[maxn],cl[maxn];
int F[maxn],dc,dfn[maxn],dy[maxn],son[maxn];
int bl[maxn],num,val[maxn*2],uu,vv,ww;
int hd[maxn],ne[maxn*2],to[maxn*2];
ll ans=0,f[N][maxn];
vector<int> id[N];
char s[10];void add(const int &x,const int &y,const int &z){to[++num]=y,ne[num]=hd[x],hd[x]=num,val[num]=z;
}void update(const int &T,int x,const int &y){ for(;x<=n;x+=x&-x) f[T][x]+=(ll)y;}
ll query(const int &T,int x){ ll an=0; for(;x;x-=x&-x) an+=(ll)f[T][x]; return an;}void Fdfs(int x,int fa){F[x]=fa,siz[x]=1;for(int i=hd[x];i;i=ne[i]) if(to[i]!=fa){dep[to[i]]=dep[x]+1,Fdfs(to[i],x),siz[x]+=siz[to[i]];if(!son[x]||siz[to[i]]>siz[son[x]]) son[x]=to[i];}
}void Sdfs(int x,int tp){dfn[x]=++dc,dy[dc]=x,cl[x]=tp;if(!son[x]) return;Sdfs(son[x],tp);for(int i=hd[x];i;i=ne[i])if(to[i]!=F[x]&&to[i]!=son[x]) Sdfs(to[i],to[i]);
}inline int LCA(int a,int b){while(cl[a]!=cl[b]){if(dep[cl[a]]>dep[cl[b]]) a=F[cl[a]];else b=F[cl[b]];}return dep[a]>dep[b]?b:a;
}inline int Get(int T,int x){return upper_bound(id[T].begin(),id[T].end(),x)-id[T].begin();
}inline void Maintain(int o,int derta){int p=to[o*2-1];if(dep[p]<dep[to[o<<1]]) p=to[o<<1];update(0,dfn[p],derta),update(0,dfn[p]+siz[p],-derta);for(int i=1,a,b;i<=200;i++) if(id[i].size()){a=Get(i,dfn[p]+siz[p]-1)-Get(i,dfn[p]-1),b=id[i].size()-a;update(i,1,a*derta),update(i,dfn[p],(b-a)*derta),update(i,dfn[p]+siz[p],(a-b)*derta);}
}inline ll calc(int qz,int p){ll an=0;for(int i=1;i<bl[qz];i++) an+=query(i,dfn[p]);for(int i=qz;i;i--){an+=query(0,dfn[i])+query(0,dfn[p])-2ll*query(0,dfn[LCA(p,i)]);if(bl[i]!=bl[i-1]) break;}return an;
}inline void prework(){Fdfs(1,0),Sdfs(1,1);for(int i=1;i<=n;i++){bl[i]=(i-1)/1000+1;id[bl[i]].pb(dfn[i]);}for(int i=1;i<=200;i++) sort(id[i].begin(),id[i].end());for(int i=1;i<n;i++) Maintain(i,val[i<<1]);
}inline void solve(){const int ha=n;while(m--){scanf("%s",s);if(s[0]=='m'){uu=read(),vv=read();if(T) uu^=ans,vv^=ans;Maintain(uu,vv-val[uu<<1]),val[uu<<1]=vv;}else{uu=read(),vv=read(),ww=read();if(T) uu^=ans,vv^=ans,ww^=ans;ans=calc(vv,ww)-calc(uu-1,ww);W(ans),puts(""),ans%=ha;}}
}int main(){
//	freopen("tree.in","r",stdin);
//	freopen("tree.out","w",stdout);n=read(),m=read(),T=read();for(int i=1;i<n;i++){uu=read(),vv=read(),ww=read();add(uu,vv,ww),add(vv,uu,ww);}prework();solve();return 0;
}

?

轉(zhuǎn)載于:https://www.cnblogs.com/JYYHH/p/9193078.html

總結(jié)

以上是生活随笔為你收集整理的「2018山东一轮集训」 Tree的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。