铃铛计数问题 解题报告
生活随笔
收集整理的這篇文章主要介紹了
铃铛计数问题 解题报告
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
U72118 鈴鐺計(jì)數(shù)問題
對(duì)點(diǎn)我們發(fā)現(xiàn)有兩種編號(hào),一種是它本身的編號(hào)用作詢問,一種是便于我們子樹/鏈的操作的重新編號(hào)。
如果對(duì)鏈樹剖作為第二編號(hào),把點(diǎn)放到二維平面內(nèi),我們就可以用個(gè)kd-tree維護(hù),需要支持一些加和詢問之類的操作,但因?yàn)橛袀€(gè)\(\log\)段,所以實(shí)際上是\(\sqrt n\log n\)的。我尋思卡卡是可以過的。
正解是分塊
我們考慮對(duì)原編號(hào)分塊
設(shè)\(f_{i,r}\)表示點(diǎn)\(i\)對(duì)塊\(r\)的貢獻(xiàn),這個(gè)可以dp出來,從父親那里轉(zhuǎn)移。
這樣我們大塊詢問和大塊修改就可以完成了
考慮小塊詢問和小塊修改
實(shí)際上我們需要支持詢問子樹和,修改單點(diǎn)值,要求詢問\(O(1)\)
考慮放到\(dfs\)序上,就成了單點(diǎn)改,區(qū)間詢問,然后再分一撥塊就可以了
寫成單點(diǎn)詢問,區(qū)間修改比較好寫
Code:
#include <cstdio> #include <cctype> #include <cmath> #include <algorithm> #define ll long long using std::min; const int SIZE=1<<21; char ibuf[SIZE],*iS,*iT; //#define gc() (iS==iT?(iT=(iS=ibuf)+fread(ibuf,1,SIZE,stdin),iS==iT?EOF:*iS++):*iS++) #define gc() getchar() template <class T> void read(T &x) {int f=0;x=0;char c=gc();while(!isdigit(c)) f|=c=='-',c=gc();while(isdigit(c)) x=x*10+c-'0',c=gc();if(f) x=-x; } const int N=1e5+10; int head[N],to[N<<1],Next[N<<1],cnt; void add(int u,int v) {to[++cnt]=v,Next[cnt]=head[u],head[u]=cnt; } int n,q,rt,yuy[N],toki[N][320],B,T,L[N],R[N],belong[N]; int dfn[N],low[N],ha[N],dfsclock; ll sum[N]; void dfs(int now,int fa) {dfn[now]=++dfsclock;ha[dfsclock]=now;for(int i=1;i<=T;i++) toki[now][i]=toki[fa][i]+(L[i]<=now&&now<=R[i]),sum[i]+=1ll*toki[now][i]*yuy[now];for(int v,i=head[now];i;i=Next[i])if((v=to[i])!=fa)dfs(v,now);low[now]=dfsclock; } ll tag[N],f[N]; void modi(int x,int d) {int pos=belong[x];for(int i=pos+1;i<=T;i++) tag[i]+=d;for(int i=x;i<=R[pos];i++) f[i]+=d; } ll qry(int x) {return f[x]+tag[belong[x]]; } int main() {freopen("data.in","r",stdin);freopen("data.out","w",stdout);read(n),read(q);for(int i=1;i<=n;i++) read(yuy[i]);for(int u,v,i=1;i<=n;i++){read(u),read(v);if(u) add(u,v),add(v,u);else rt=v;}B=sqrt(n)+1,T=(n-1)/B+1;for(int i=1;i<=T;i++){L[i]=R[i-1]+1,R[i]=min(i*B,n);for(int j=L[i];j<=R[i];j++)belong[j]=i;}dfs(rt,0);for(int i=1;i<=n;i++) f[i]=f[i-1]+yuy[ha[i]];for(int op,l,r,i=1;i<=q;i++){read(op),read(l),read(r);if(op==1){int d=r-yuy[l];yuy[l]=r;for(int j=1;j<=T;j++)sum[j]+=1ll*d*toki[l][j];modi(dfn[l],d);}else{int lp=belong[l],rp=belong[r];ll ans=0;if(rp-lp<=1){for(int j=l;j<=r;j++)ans+=qry(low[j])-qry(dfn[j]-1);}else{for(int j=l;j<=R[lp];j++) ans+=qry(low[j])-qry(dfn[j]-1);for(int j=lp+1;j<rp;j++) ans+=sum[j];for(int j=L[rp];j<=r;j++) ans+=qry(low[j])-qry(dfn[j]-1);}printf("%lld\n",ans);}}return 0; }2019.5.23
轉(zhuǎn)載于:https://www.cnblogs.com/butterflydew/p/10912730.html
總結(jié)
以上是生活随笔為你收集整理的铃铛计数问题 解题报告的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 2019ug最新版本是多少_UG NX
- 下一篇: Lambert 投影转换相关代码