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

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

poj3966

發(fā)布時(shí)間:2023/12/18 编程问答 25 豆豆
生活随笔 收集整理的這篇文章主要介紹了 poj3966 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

鏈接:點(diǎn)擊打開(kāi)鏈接

題意:給出一顆樹(shù),和樹(shù)上每個(gè)節(jié)點(diǎn)的權(quán)值,有三種操作,分別為把C1與C2的路徑上的所有點(diǎn)的權(quán)值加K,把C1與C2的路徑上的所有點(diǎn)的權(quán)值減K,和詢(xún)問(wèn)c節(jié)點(diǎn)的權(quán)值

代碼:

//#pragma comment(linker, "/STACK:1024000000,1024000000") #include <stdio.h> #include <string.h> #include <iostream> #include <algorithm> using namespace std; const int SIZE=50005; int n,m,q,tim; int sum[4*SIZE],add[4*SIZE]; //sum為線段樹(shù),add為懶惰標(biāo)記 int num[SIZE],siz[SIZE],top[SIZE],son[SIZE]; //num為節(jié)點(diǎn)的權(quán)值,fa為父節(jié)點(diǎn),son為重兒子,top為重鏈的第一個(gè)節(jié)點(diǎn) int dep[SIZE],tid[SIZE],ran[SIZE],fa[SIZE]; //dep為節(jié)點(diǎn)深度,tid為節(jié)點(diǎn)剖分后的編號(hào),ran為剖分后的新編號(hào)實(shí)際的點(diǎn) int head[SIZE],to[2*SIZE],nex[2*SIZE],edge; //siz為以當(dāng)前節(jié)點(diǎn)為根節(jié)點(diǎn)的子樹(shù)含的節(jié)點(diǎn)數(shù) void addedge(int u,int v){to[edge]=v,nex[edge]=head[u],head[u]=edge++;//基本定義:to[edge]=u,nex[edge]=head[v],head[v]=edge++;//重兒子:當(dāng)前節(jié)點(diǎn)中siz最大的就為當(dāng)前節(jié)點(diǎn)的重兒子 } //重邊:節(jié)點(diǎn)與其重兒子的連邊 void dfs1(int u,int father,int d){ //重鏈:重變連成的路徑int i,v; //因?yàn)檫厰?shù)可能很多因此用前向星建圖fa[u]=father; //因?yàn)槲覀円纸獬鏊械闹劓溡虼?#xff0c;需要知道每個(gè)節(jié)點(diǎn)的重兒子 dep[u]=d; //同時(shí)求出父節(jié)點(diǎn)和節(jié)點(diǎn)的深度,用于后續(xù)查詢(xún)時(shí)使用 siz[u]=1;for(i=head[u];~i;i=nex[i]){v=to[i];if(v!=father){ //每條邊都是雙向邊,因此v!=fatherdfs1(v,u,d+1);siz[u]+=siz[v];if(son[u]==-1||siz[v]>siz[son[u]]) //沒(méi)有重兒子或則新的節(jié)點(diǎn)的siz大于原來(lái)的sizson[u]=v; //更新重兒子 }} } void dfs2(int u,int tp){int i,v;top[u]=tp;tid[u]=tim++; //將節(jié)點(diǎn)重新編號(hào),同一條重鏈上的點(diǎn)放在維護(hù)的ran[tid[u]]=u; //的數(shù)據(jù)結(jié)構(gòu)中連續(xù)的空間內(nèi),從而才能實(shí)現(xiàn)高效if(son[u]==-1) //的查詢(xún)和詢(xún)問(wèn)return;dfs2(son[u],tp); //根據(jù)dfs1找出的重兒子從而找出重鏈for(i=head[u];~i;i=nex[i]){v=to[i];if(v!=son[u]&&v!=fa[u])dfs2(v,v); //新的重鏈} } void pushdown(int rt,int m){ //線段樹(shù)區(qū)間更新if(add[rt]){add[rt<<1]+=add[rt];add[rt<<1|1]+=add[rt];sum[rt<<1]+=(m-(m>>1))*add[rt];sum[rt<<1|1]+=(m>>1)*add[rt];add[rt]=0;} } void build(int l,int r,int rt){int m;add[rt]=0;if(l==r){sum[rt]=num[ran[l]];return;}m=(l+r)>>1;build(l,m,rt<<1);build(m+1,r,rt<<1|1);sum[rt]=max(sum[rt],sum[rt<<1|1]); } void update(int L,int R,int p,int l,int r,int rt){int m;if(L<=l&&r<=R){add[rt]+=p;sum[rt]+=(r-l+1)*p;return;}pushdown(rt,r-l+1);m=(l+r)>>1;if(L<=m)update(L,R,p,l,m,rt<<1);if(R>m)update(L,R,p,m+1,r,rt<<1|1);sum[rt]=max(sum[rt<<1],sum[rt<<1|1]); } int query(int p,int l,int r,int rt){int m,ans;ans=0;if(l==r)return sum[rt];pushdown(rt,r-l+1);m=(l+r)>>1;if(p<=m)ans=query(p,l,m,rt<<1);elseans=query(p,m+1,r,rt<<1|1);sum[rt]=max(sum[rt<<1],sum[rt<<1|1]);return ans; } void change(int x,int y,int p){ //對(duì)這顆樹(shù)進(jìn)行更新 while(top[x]!=top[y]){ //不在同一條重鏈上的點(diǎn),盡可能湊到同一條重鏈上 if(dep[top[x]]<dep[top[y]]) //在同一條重鏈上的則可以直接修改swap(x,y); //可以看下面的鏈接,關(guān)于更新講的很詳細(xì)update(tid[top[x]],tid[x],p,1,n,1); //http://blog.sina.com.cn/s/blog_7a1746820100wp67.htmlx=fa[top[x]];}if(dep[x]>dep[y])swap(x,y);update(tid[x],tid[y],p,1,n,1); } int main(){ //因?yàn)橐粋€(gè)樹(shù)的所有重鏈覆蓋了所有的點(diǎn),因此int i,x,y,z; //樹(shù)鏈剖分就是將所有重鏈分解出來(lái),并用其它c(diǎn)har c; //的數(shù)據(jù)結(jié)構(gòu)進(jìn)行維護(hù),從而高效的實(shí)現(xiàn)查找和while(scanf("%d%d%d",&n,&m,&q)!=EOF){ //詢(xún)問(wèn) tim=1,edge=0;memset(son,-1,sizeof(son));memset(head,-1,sizeof(head));for(i=1;i<=n;i++)scanf("%d",&num[i]);for(i=1;i<=m;i++){scanf("%d%d",&x,&y);addedge(x,y);}dfs1(1,0,0);dfs2(1,1);build(1,n,1);while(q--){scanf(" %c",&c);if(c=='Q'){scanf("%d",&x);printf("%d\n",query(tid[x],1,n,1));}else{scanf("%d%d%d",&x,&y,&z);if(c=='D')change(x,y,-z);elsechange(x,y,z);}}}return 0; }


?

總結(jié)

以上是生活随笔為你收集整理的poj3966的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

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